Version Description
- 2017-12-18 =
- Added: New option "Auto TLS" for SMTP mailer. Default is enabled. Migration routine for all sites.
- Changed: Improve debug output - clear styles and context-aware content.
- Changed: Better exceptions handling for Google authentication process.
- Changed: Do not sanitize passwords, api keys etc - as they may contain special characters in certain order and sanitization will break those values.
- Changed: Improve wording of some helpful texts inside plugin admin area.
- Fixed: Do not include certain files in dependency libraries that are not used by Google mailer. This should stop flagging plugin by Wordfence and VaultPress.
- Fixed: Constants usage is working now, to define the SMTP password, for example.
- Fixed: Notice for default mailer.
Download this release
Release Info
Developer | slaFFik |
Plugin | WP Mail SMTP by WPForms |
Version | 1.1.0 |
Comparing to | |
See all releases |
Code changes from version 1.0.2 to 1.1.0
- assets/js/smtp-admin.js +43 -36
- assets/js/smtp-admin.min.js +1 -1
- class-wpms-am-notification.php +450 -450
- languages/wp-mail-smtp.pot +25 -9
- readme.txt +10 -0
- src/AM_Notification.php +452 -452
- src/Admin/Area.php +457 -457
- src/Admin/PageAbstract.php +66 -66
- src/Admin/PageInterface.php +45 -45
- src/Admin/Pages/Auth.php +56 -56
- src/Admin/Pages/Misc.php +99 -99
- src/Admin/Pages/Settings.php +236 -236
- src/Admin/Pages/Test.php +235 -208
- src/Core.php +239 -213
- src/MailCatcher.php +66 -66
- src/Migration.php +245 -245
- src/Options.php +547 -469
- src/Processor.php +175 -170
- src/Providers/AuthAbstract.php +22 -22
- src/Providers/AuthInterface.php +19 -19
- src/Providers/Gmail/Auth.php +314 -299
- src/Providers/Gmail/Mailer.php +173 -173
- src/Providers/Gmail/Options.php +131 -131
- src/Providers/Loader.php +178 -178
- src/Providers/Mail/Options.php +42 -42
- src/Providers/MailerAbstract.php +346 -346
- src/Providers/MailerInterface.php +139 -139
- src/Providers/Mailgun/Mailer.php +299 -299
- src/Providers/Mailgun/Options.php +106 -106
- src/Providers/OptionAbstract.php +312 -291
- src/Providers/OptionInterface.php +64 -64
- src/Providers/Pepipost/Options.php +29 -29
- src/Providers/SMTP/Options.php +45 -45
- src/Providers/Sendgrid/Mailer.php +294 -294
- src/Providers/Sendgrid/Options.php +89 -89
- src/Upgrade.php +71 -0
- src/WP.php +140 -140
- vendor/autoload.php +2 -2
- vendor/composer/ClassLoader.php +45 -13
- vendor/composer/LICENSE +1 -1
- vendor/composer/autoload_classmap.php +228 -0
- vendor/composer/autoload_real.php +9 -18
- vendor/composer/autoload_static.php +233 -5
- vendor/phpseclib/phpseclib/phpseclib/Crypt/Base.php +0 -2558
- vendor/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php +0 -577
- vendor/phpseclib/phpseclib/phpseclib/Crypt/DES.php +0 -1443
- vendor/phpseclib/phpseclib/phpseclib/Crypt/Hash.php +0 -824
- vendor/phpseclib/phpseclib/phpseclib/Crypt/RC2.php +0 -688
- vendor/phpseclib/phpseclib/phpseclib/Crypt/RC4.php +0 -342
- vendor/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php +0 -460
- vendor/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php +0 -808
- vendor/phpseclib/phpseclib/phpseclib/File/ANSI.php +0 -577
- vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php +0 -1325
- vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Element.php +0 -47
- vendor/phpseclib/phpseclib/phpseclib/File/X509.php +0 -4846
- vendor/phpseclib/phpseclib/phpseclib/Net/SCP.php +0 -337
- vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php +0 -1951
assets/js/smtp-admin.js
CHANGED
@@ -1,36 +1,43 @@
|
|
1 |
-
/* globals jQuery */
|
2 |
-
jQuery( document ).ready( function ( $ ) {
|
3 |
-
|
4 |
-
$( '.wp-mail-smtp-mailer input' ).click( function () {
|
5 |
-
if ( $( this ).prop( 'disabled' ) ) {
|
6 |
-
return false;
|
7 |
-
}
|
8 |
-
|
9 |
-
// Deselect the current mailer.
|
10 |
-
$( '.wp-mail-smtp-mailer' ).removeClass( 'active' );
|
11 |
-
// Select the correct one.
|
12 |
-
$( this ).parents( '.wp-mail-smtp-mailer' ).addClass( 'active' );
|
13 |
-
|
14 |
-
$( '.wp-mail-smtp-mailer-option' ).addClass( 'hidden' ).removeClass( 'active' );
|
15 |
-
$( '.wp-mail-smtp-mailer-option-' + $( this ).val() ).addClass( 'active' ).removeClass( 'hidden' );
|
16 |
-
} );
|
17 |
-
|
18 |
-
$( '.wp-mail-smtp-mailer-image' ).click( function () {
|
19 |
-
$( this ).parents( '.wp-mail-smtp-mailer' ).find( 'input' ).trigger( 'click' );
|
20 |
-
} );
|
21 |
-
|
22 |
-
$( '.wp-mail-smtp-setting-copy' ).click( function ( e ) {
|
23 |
-
e.preventDefault();
|
24 |
-
|
25 |
-
var target = $( '#' + $( this ).data( 'source_id' ) ).get(0);
|
26 |
-
|
27 |
-
target.select();
|
28 |
-
|
29 |
-
document.execCommand( 'Copy' );
|
30 |
-
} );
|
31 |
-
|
32 |
-
$( '#wp-mail-smtp-setting-smtp-auth' ).change(function() {
|
33 |
-
$( '#wp-mail-smtp-setting-row-smtp-user, #wp-mail-smtp-setting-row-smtp-pass' ).toggleClass( 'inactive' );
|
34 |
-
});
|
35 |
-
|
36 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* globals jQuery */
|
2 |
+
jQuery( document ).ready( function ( $ ) {
|
3 |
+
|
4 |
+
$( '.wp-mail-smtp-mailer input' ).click( function () {
|
5 |
+
if ( $( this ).prop( 'disabled' ) ) {
|
6 |
+
return false;
|
7 |
+
}
|
8 |
+
|
9 |
+
// Deselect the current mailer.
|
10 |
+
$( '.wp-mail-smtp-mailer' ).removeClass( 'active' );
|
11 |
+
// Select the correct one.
|
12 |
+
$( this ).parents( '.wp-mail-smtp-mailer' ).addClass( 'active' );
|
13 |
+
|
14 |
+
$( '.wp-mail-smtp-mailer-option' ).addClass( 'hidden' ).removeClass( 'active' );
|
15 |
+
$( '.wp-mail-smtp-mailer-option-' + $( this ).val() ).addClass( 'active' ).removeClass( 'hidden' );
|
16 |
+
} );
|
17 |
+
|
18 |
+
$( '.wp-mail-smtp-mailer-image' ).click( function () {
|
19 |
+
$( this ).parents( '.wp-mail-smtp-mailer' ).find( 'input' ).trigger( 'click' );
|
20 |
+
} );
|
21 |
+
|
22 |
+
$( '.wp-mail-smtp-setting-copy' ).click( function ( e ) {
|
23 |
+
e.preventDefault();
|
24 |
+
|
25 |
+
var target = $( '#' + $( this ).data( 'source_id' ) ).get(0);
|
26 |
+
|
27 |
+
target.select();
|
28 |
+
|
29 |
+
document.execCommand( 'Copy' );
|
30 |
+
} );
|
31 |
+
|
32 |
+
$( '#wp-mail-smtp-setting-smtp-auth' ).change( function() {
|
33 |
+
$( '#wp-mail-smtp-setting-row-smtp-user, #wp-mail-smtp-setting-row-smtp-pass' ).toggleClass( 'inactive' );
|
34 |
+
});
|
35 |
+
|
36 |
+
$( '#wp-mail-smtp-setting-row-smtp-encryption input').change( function() {
|
37 |
+
if ( 'tls' === $(this).val() ) {
|
38 |
+
$(' #wp-mail-smtp-setting-row-smtp-autotls' ).addClass( 'inactive' );
|
39 |
+
} else {
|
40 |
+
$( '#wp-mail-smtp-setting-row-smtp-autotls' ).removeClass( 'inactive' );
|
41 |
+
}
|
42 |
+
} );
|
43 |
+
} );
|
assets/js/smtp-admin.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
jQuery(document).ready(function(
|
1 |
+
jQuery(document).ready(function(t){t(".wp-mail-smtp-mailer input").click(function(){if(t(this).prop("disabled"))return!1;t(".wp-mail-smtp-mailer").removeClass("active"),t(this).parents(".wp-mail-smtp-mailer").addClass("active"),t(".wp-mail-smtp-mailer-option").addClass("hidden").removeClass("active"),t(".wp-mail-smtp-mailer-option-"+t(this).val()).addClass("active").removeClass("hidden")}),t(".wp-mail-smtp-mailer-image").click(function(){t(this).parents(".wp-mail-smtp-mailer").find("input").trigger("click")}),t(".wp-mail-smtp-setting-copy").click(function(i){i.preventDefault(),t("#"+t(this).data("source_id")).get(0).select(),document.execCommand("Copy")}),t("#wp-mail-smtp-setting-smtp-auth").change(function(){t("#wp-mail-smtp-setting-row-smtp-user, #wp-mail-smtp-setting-row-smtp-pass").toggleClass("inactive")}),t("#wp-mail-smtp-setting-row-smtp-encryption input").change(function(){"tls"===t(this).val()?t(" #wp-mail-smtp-setting-row-smtp-autotls").addClass("inactive"):t("#wp-mail-smtp-setting-row-smtp-autotls").removeClass("inactive")})});
|
class-wpms-am-notification.php
CHANGED
@@ -1,450 +1,450 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Awesome Motive Notifications
|
5 |
-
*
|
6 |
-
* This creates a custom post type (if it doesn't exist) and calls the API to
|
7 |
-
* retrieve notifications for this product.
|
8 |
-
*
|
9 |
-
* @package AwesomeMotive
|
10 |
-
* @author Benjamin Rojas
|
11 |
-
* @license GPL-2.0+
|
12 |
-
* @copyright Copyright (c) 2017, Retyp LLC
|
13 |
-
* @version 1.0.2
|
14 |
-
*/
|
15 |
-
class WPMS_AM_Notification {
|
16 |
-
/**
|
17 |
-
* The api url we are calling.
|
18 |
-
*
|
19 |
-
* @since 1.0.0
|
20 |
-
*
|
21 |
-
* @var string
|
22 |
-
*/
|
23 |
-
public $api_url = 'https://api.awesomemotive.com/v1/notification/';
|
24 |
-
|
25 |
-
/**
|
26 |
-
* A unique slug for this plugin.
|
27 |
-
* (Not the WordPress plugin slug)
|
28 |
-
*
|
29 |
-
* @since 1.0.0
|
30 |
-
*
|
31 |
-
* @var string
|
32 |
-
*/
|
33 |
-
public $plugin;
|
34 |
-
|
35 |
-
/**
|
36 |
-
* The current plugin version.
|
37 |
-
*
|
38 |
-
* @since 1.0.0
|
39 |
-
*
|
40 |
-
* @var string
|
41 |
-
*/
|
42 |
-
public $plugin_version;
|
43 |
-
|
44 |
-
/**
|
45 |
-
* Flag if a notice has been registered.
|
46 |
-
*
|
47 |
-
* @since 1.0.0
|
48 |
-
*
|
49 |
-
* @var bool
|
50 |
-
*/
|
51 |
-
public static $registered = false;
|
52 |
-
|
53 |
-
/**
|
54 |
-
* Construct.
|
55 |
-
*
|
56 |
-
* @since 1.0.0
|
57 |
-
*
|
58 |
-
* @param string $plugin The plugin slug.
|
59 |
-
* @param mixed $version The version of the plugin.
|
60 |
-
*/
|
61 |
-
public function __construct( $plugin = '', $version = 0 ) {
|
62 |
-
$this->plugin = $plugin;
|
63 |
-
$this->plugin_version = $version;
|
64 |
-
|
65 |
-
add_action( 'init', array( $this, 'custom_post_type' ) );
|
66 |
-
add_action( 'admin_init', array( $this, 'get_remote_notifications' ), 100 );
|
67 |
-
add_action( 'admin_notices', array( $this, 'display_notifications' ) );
|
68 |
-
add_action( 'wp_ajax_am_notification_dismiss', array( $this, 'dismiss_notification' ) );
|
69 |
-
}
|
70 |
-
|
71 |
-
/**
|
72 |
-
* Registers a custom post type.
|
73 |
-
*
|
74 |
-
* @since 1.0.0
|
75 |
-
*/
|
76 |
-
public function custom_post_type() {
|
77 |
-
register_post_type( 'amn_' . $this->plugin, array(
|
78 |
-
'label' => $this->plugin . ' Announcements',
|
79 |
-
'can_export' => false,
|
80 |
-
'supports' => false,
|
81 |
-
) );
|
82 |
-
}
|
83 |
-
|
84 |
-
/**
|
85 |
-
* Retrieve the remote notifications if the time has expired.
|
86 |
-
*
|
87 |
-
* @since 1.0.0
|
88 |
-
*/
|
89 |
-
public function get_remote_notifications() {
|
90 |
-
if ( ! current_user_can( apply_filters( 'am_notifications_display', 'manage_options' ) ) ) {
|
91 |
-
return;
|
92 |
-
}
|
93 |
-
|
94 |
-
$last_checked = get_option( '_amn_' . $this->plugin . '_last_checked', strtotime( '-1 week' ) );
|
95 |
-
|
96 |
-
if ( $last_checked < strtotime( 'today midnight' ) ) {
|
97 |
-
$plugin_notifications = $this->get_plugin_notifications( 1 );
|
98 |
-
$notification_id = null;
|
99 |
-
|
100 |
-
if ( ! empty( $plugin_notifications ) ) {
|
101 |
-
// Unset it from the array.
|
102 |
-
$notification = $plugin_notifications[0];
|
103 |
-
$notification_id = get_post_meta( $notification->ID, 'notification_id', true );
|
104 |
-
}
|
105 |
-
|
106 |
-
$response = wp_remote_retrieve_body( wp_remote_post( $this->api_url, array(
|
107 |
-
'body' => array(
|
108 |
-
'slug' => $this->plugin,
|
109 |
-
'version' => $this->plugin_version,
|
110 |
-
'last_notification' => $notification_id,
|
111 |
-
),
|
112 |
-
) ) );
|
113 |
-
|
114 |
-
$data = json_decode( $response );
|
115 |
-
|
116 |
-
if ( ! empty( $data->id ) ) {
|
117 |
-
$notifications = array();
|
118 |
-
|
119 |
-
foreach ( (array) $data->slugs as $slug ) {
|
120 |
-
$notifications = array_merge(
|
121 |
-
$notifications,
|
122 |
-
(array) get_posts(
|
123 |
-
array(
|
124 |
-
'post_type' => 'amn_' . $slug,
|
125 |
-
'post_status' => 'all',
|
126 |
-
'meta_key' => 'notification_id',
|
127 |
-
'meta_value' => $data->id,
|
128 |
-
)
|
129 |
-
)
|
130 |
-
);
|
131 |
-
}
|
132 |
-
|
133 |
-
if ( empty( $notifications ) ) {
|
134 |
-
$new_notification_id = wp_insert_post( array(
|
135 |
-
'post_content' => wp_kses_post( $data->content ),
|
136 |
-
'post_type' => 'amn_' . $this->plugin,
|
137 |
-
) );
|
138 |
-
|
139 |
-
update_post_meta( $new_notification_id, 'notification_id', absint( $data->id ) );
|
140 |
-
update_post_meta( $new_notification_id, 'type', sanitize_text_field( trim( $data->type ) ) );
|
141 |
-
update_post_meta( $new_notification_id, 'dismissable', (bool) $data->dismissible ? 1 : 0 );
|
142 |
-
update_post_meta( $new_notification_id, 'location', function_exists( 'wp_json_encode' ) ? wp_json_encode( $data->location ) : json_encode( $data->location ) );
|
143 |
-
update_post_meta( $new_notification_id, 'version', sanitize_text_field( trim( $data->version ) ) );
|
144 |
-
update_post_meta( $new_notification_id, 'viewed', 0 );
|
145 |
-
update_post_meta( $new_notification_id, 'expiration', $data->expiration ? absint( $data->expiration ) : false );
|
146 |
-
update_post_meta( $new_notification_id, 'plans', function_exists( 'wp_json_encode' ) ? wp_json_encode( $data->plans ) : json_encode( $data->plans ) );
|
147 |
-
}
|
148 |
-
}
|
149 |
-
|
150 |
-
// Possibly revoke notifications.
|
151 |
-
if ( ! empty( $data->revoked ) ) {
|
152 |
-
$this->revoke_notifications( $data->revoked );
|
153 |
-
}
|
154 |
-
|
155 |
-
// Set the option now so we can't run this again until after 24 hours.
|
156 |
-
update_option( '_amn_' . $this->plugin . '_last_checked', strtotime( 'today midnight' ) );
|
157 |
-
}
|
158 |
-
}
|
159 |
-
|
160 |
-
/**
|
161 |
-
* Get local plugin notifications that have already been set.
|
162 |
-
*
|
163 |
-
* @since 1.0.0
|
164 |
-
*
|
165 |
-
* @param integer $limit Set the limit for how many posts to retrieve.
|
166 |
-
* @param array $args Any top-level arguments to add to the array.
|
167 |
-
*
|
168 |
-
* @return WP_Post[] WP_Post that match the query.
|
169 |
-
*/
|
170 |
-
public function get_plugin_notifications( $limit = -1, $args = array() ) {
|
171 |
-
return get_posts(
|
172 |
-
array(
|
173 |
-
'posts_per_page' => $limit,
|
174 |
-
'post_type' => 'amn_' . $this->plugin,
|
175 |
-
) + $args
|
176 |
-
);
|
177 |
-
}
|
178 |
-
|
179 |
-
/**
|
180 |
-
* Display any notifications that should be displayed.
|
181 |
-
*
|
182 |
-
* @since 1.0.0
|
183 |
-
*/
|
184 |
-
public function display_notifications() {
|
185 |
-
if ( ! current_user_can( apply_filters( 'am_notifications_display', 'manage_options' ) ) ) {
|
186 |
-
return;
|
187 |
-
}
|
188 |
-
|
189 |
-
$plugin_notifications = $this->get_plugin_notifications( -1, array(
|
190 |
-
'post_status' => 'all',
|
191 |
-
'meta_key' => 'viewed',
|
192 |
-
'meta_value' => '0',
|
193 |
-
) );
|
194 |
-
|
195 |
-
$plugin_notifications = $this->validate_notifications( $plugin_notifications );
|
196 |
-
|
197 |
-
if ( ! empty( $plugin_notifications ) && ! self::$registered ) {
|
198 |
-
foreach ( $plugin_notifications as $notification ) {
|
199 |
-
$dismissable = get_post_meta( $notification->ID, 'dismissable', true );
|
200 |
-
$type = get_post_meta( $notification->ID, 'type', true );
|
201 |
-
?>
|
202 |
-
<div class="am-notification am-notification-<?php echo $notification->ID; ?> notice notice-<?php echo $type; ?><?php echo $dismissable ? ' is-dismissible' : ''; ?>">
|
203 |
-
<?php echo $notification->post_content; ?>
|
204 |
-
</div>
|
205 |
-
<script type="text/javascript">
|
206 |
-
jQuery(document).ready(function ($) {
|
207 |
-
$(document).on('click', '.am-notification-<?php echo $notification->ID; ?> button.notice-dismiss', function (event) {
|
208 |
-
$.post(ajaxurl, {
|
209 |
-
action: 'am_notification_dismiss',
|
210 |
-
notification_id: '<?php echo $notification->ID; ?>'
|
211 |
-
});
|
212 |
-
});
|
213 |
-
});
|
214 |
-
</script>
|
215 |
-
<?php
|
216 |
-
}
|
217 |
-
|
218 |
-
self::$registered = true;
|
219 |
-
}
|
220 |
-
}
|
221 |
-
|
222 |
-
/**
|
223 |
-
* Validate the notifications before displaying them.
|
224 |
-
*
|
225 |
-
* @since 1.0.0
|
226 |
-
*
|
227 |
-
* @param array $plugin_notifications An array of plugin notifications.
|
228 |
-
*
|
229 |
-
* @return array A filtered array of plugin notifications.
|
230 |
-
*/
|
231 |
-
public function validate_notifications( $plugin_notifications ) {
|
232 |
-
global $pagenow;
|
233 |
-
|
234 |
-
foreach ( $plugin_notifications as $key => $notification ) {
|
235 |
-
// Location validation.
|
236 |
-
$location = (array) json_decode( get_post_meta( $notification->ID, 'location', true ) );
|
237 |
-
$continue = false;
|
238 |
-
if ( ! in_array( 'everywhere', $location, true ) ) {
|
239 |
-
if ( in_array( 'index.php', $location, true ) && 'index.php' === $pagenow ) {
|
240 |
-
$continue = true;
|
241 |
-
}
|
242 |
-
|
243 |
-
if ( in_array( 'plugins.php', $location, true ) && 'plugins.php' === $pagenow ) {
|
244 |
-
$continue = true;
|
245 |
-
}
|
246 |
-
|
247 |
-
if ( ! $continue ) {
|
248 |
-
unset( $plugin_notifications[ $key ] );
|
249 |
-
}
|
250 |
-
}
|
251 |
-
|
252 |
-
// Plugin validation (OR conditional).
|
253 |
-
$plugins = (array) json_decode( get_post_meta( $notification->ID, 'plugins', true ) );
|
254 |
-
$continue = false;
|
255 |
-
if ( ! empty( $plugins ) ) {
|
256 |
-
foreach ( $plugins as $plugin ) {
|
257 |
-
if ( is_plugin_active( $plugin ) ) {
|
258 |
-
$continue = true;
|
259 |
-
}
|
260 |
-
}
|
261 |
-
|
262 |
-
if ( ! $continue ) {
|
263 |
-
unset( $plugin_notifications[ $key ] );
|
264 |
-
}
|
265 |
-
}
|
266 |
-
|
267 |
-
// Theme validation.
|
268 |
-
$theme = get_post_meta( $notification->ID, 'theme', true );
|
269 |
-
$continue = (string) wp_get_theme() === $theme;
|
270 |
-
|
271 |
-
if ( ! empty( $theme ) && ! $continue ) {
|
272 |
-
unset( $plugin_notifications[ $key ] );
|
273 |
-
}
|
274 |
-
|
275 |
-
// Version validation.
|
276 |
-
$version = get_post_meta( $notification->ID, 'version', true );
|
277 |
-
$continue = false;
|
278 |
-
if ( ! empty( $version ) ) {
|
279 |
-
if ( version_compare( $this->plugin_version, $version, '<=' ) ) {
|
280 |
-
$continue = true;
|
281 |
-
}
|
282 |
-
|
283 |
-
if ( ! $continue ) {
|
284 |
-
unset( $plugin_notifications[ $key ] );
|
285 |
-
}
|
286 |
-
}
|
287 |
-
|
288 |
-
// Expiration validation.
|
289 |
-
$expiration = get_post_meta( $notification->ID, 'expiration', true );
|
290 |
-
$continue = false;
|
291 |
-
if ( ! empty( $expiration ) ) {
|
292 |
-
if ( $expiration > time() ) {
|
293 |
-
$continue = true;
|
294 |
-
}
|
295 |
-
|
296 |
-
if ( ! $continue ) {
|
297 |
-
unset( $plugin_notifications[ $key ] );
|
298 |
-
}
|
299 |
-
}
|
300 |
-
|
301 |
-
// Plan validation.
|
302 |
-
$plans = (array) json_decode( get_post_meta( $notification->ID, 'plans', true ) );
|
303 |
-
$continue = false;
|
304 |
-
if ( ! empty( $plans ) ) {
|
305 |
-
$level = $this->get_plan_level();
|
306 |
-
if ( in_array( $level, $plans, true ) ) {
|
307 |
-
$continue = true;
|
308 |
-
}
|
309 |
-
|
310 |
-
if ( ! $continue ) {
|
311 |
-
unset( $plugin_notifications[ $key ] );
|
312 |
-
}
|
313 |
-
}
|
314 |
-
}
|
315 |
-
|
316 |
-
return $plugin_notifications;
|
317 |
-
}
|
318 |
-
|
319 |
-
/**
|
320 |
-
* Grab the current plan level.
|
321 |
-
*
|
322 |
-
* @since 1.0.0
|
323 |
-
*
|
324 |
-
* @return string The current plan level.
|
325 |
-
*/
|
326 |
-
public function get_plan_level() {
|
327 |
-
// Prepare variables.
|
328 |
-
$key = '';
|
329 |
-
$level = '';
|
330 |
-
$option = false;
|
331 |
-
switch ( $this->plugin ) {
|
332 |
-
case 'wpforms' :
|
333 |
-
$option = get_option( 'wpforms_license' );
|
334 |
-
$key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
|
335 |
-
$level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
|
336 |
-
|
337 |
-
// Possibly check for a constant.
|
338 |
-
if ( empty( $key ) && defined( 'WPFORMS_LICENSE_KEY' ) ) {
|
339 |
-
$key = WPFORMS_LICENSE_KEY;
|
340 |
-
}
|
341 |
-
break;
|
342 |
-
case 'mi' :
|
343 |
-
$option = get_option( 'monsterinsights_license' );
|
344 |
-
$key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
|
345 |
-
$level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
|
346 |
-
|
347 |
-
// Possibly check for a constant.
|
348 |
-
if ( empty( $key ) && defined( 'MONSTERINSIGHTS_LICENSE_KEY' ) && is_string( MONSTERINSIGHTS_LICENSE_KEY ) && strlen( MONSTERINSIGHTS_LICENSE_KEY ) > 10 ) {
|
349 |
-
$key = MONSTERINSIGHTS_LICENSE_KEY;
|
350 |
-
}
|
351 |
-
break;
|
352 |
-
case 'sol' :
|
353 |
-
$option = get_option( 'soliloquy' );
|
354 |
-
$key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
|
355 |
-
$level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
|
356 |
-
|
357 |
-
// Possibly check for a constant.
|
358 |
-
if ( empty( $key ) && defined( 'SOLILOQUY_LICENSE_KEY' ) ) {
|
359 |
-
$key = SOLILOQUY_LICENSE_KEY;
|
360 |
-
}
|
361 |
-
break;
|
362 |
-
case 'envira' :
|
363 |
-
$option = get_option( 'envira_gallery' );
|
364 |
-
$key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
|
365 |
-
$level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
|
366 |
-
|
367 |
-
// Possibly check for a constant.
|
368 |
-
if ( empty( $key ) && defined( 'ENVIRA_LICENSE_KEY' ) ) {
|
369 |
-
$key = ENVIRA_LICENSE_KEY;
|
370 |
-
}
|
371 |
-
break;
|
372 |
-
case 'om' :
|
373 |
-
$option = get_option( 'optin_monster_api' );
|
374 |
-
$key = is_array( $option ) && isset( $option['api']['apikey'] ) ? $option['api']['apikey'] : '';
|
375 |
-
|
376 |
-
// Possibly check for a constant.
|
377 |
-
if ( empty( $key ) && defined( 'OPTINMONSTER_REST_API_LICENSE_KEY' ) ) {
|
378 |
-
$key = OPTINMONSTER_REST_API_LICENSE_KEY;
|
379 |
-
}
|
380 |
-
|
381 |
-
// If the key is still empty, check for the old legacy key.
|
382 |
-
if ( empty( $key ) ) {
|
383 |
-
$key = is_array( $option ) && isset( $option['api']['key'] ) ? $option['api']['key'] : '';
|
384 |
-
}
|
385 |
-
break;
|
386 |
-
}
|
387 |
-
|
388 |
-
// Possibly set the level to 'none' if the key is empty and no level has been set.
|
389 |
-
if ( empty( $key ) && empty( $level ) ) {
|
390 |
-
$level = 'none';
|
391 |
-
}
|
392 |
-
|
393 |
-
// Normalize the level.
|
394 |
-
switch ( $level ) {
|
395 |
-
case 'bronze' :
|
396 |
-
case 'personal' :
|
397 |
-
$level = 'basic';
|
398 |
-
break;
|
399 |
-
case 'silver' :
|
400 |
-
case 'multi' :
|
401 |
-
$level = 'plus';
|
402 |
-
break;
|
403 |
-
case 'gold' :
|
404 |
-
case 'developer' :
|
405 |
-
$level = 'pro';
|
406 |
-
break;
|
407 |
-
case 'platinum' :
|
408 |
-
case 'master' :
|
409 |
-
$level = 'ultimate';
|
410 |
-
break;
|
411 |
-
}
|
412 |
-
|
413 |
-
// Return the plan level.
|
414 |
-
return $level;
|
415 |
-
}
|
416 |
-
|
417 |
-
/**
|
418 |
-
* Dismiss the notification via AJAX.
|
419 |
-
*
|
420 |
-
* @since 1.0.0
|
421 |
-
*/
|
422 |
-
public function dismiss_notification() {
|
423 |
-
if ( ! current_user_can( apply_filters( 'am_notifications_display', 'manage_options' ) ) ) {
|
424 |
-
die;
|
425 |
-
}
|
426 |
-
|
427 |
-
$notification_id = intval( $_POST['notification_id'] );
|
428 |
-
update_post_meta( $notification_id, 'viewed', 1 );
|
429 |
-
die;
|
430 |
-
}
|
431 |
-
|
432 |
-
/**
|
433 |
-
* Revokes notifications.
|
434 |
-
*
|
435 |
-
* @since 1.0.0
|
436 |
-
*
|
437 |
-
* @param array $ids An array of notification IDs to revoke.
|
438 |
-
*/
|
439 |
-
public function revoke_notifications( $ids ) {
|
440 |
-
// Loop through each of the IDs and find the post that has it as meta.
|
441 |
-
foreach ( (array) $ids as $id ) {
|
442 |
-
$notifications = $this->get_plugin_notifications( -1, array( 'post_status' => 'all', 'meta_key' => 'notification_id', 'meta_value' => $id ) );
|
443 |
-
if ( $notifications ) {
|
444 |
-
foreach ( $notifications as $notification ) {
|
445 |
-
update_post_meta( $notification->ID, 'viewed', 1 );
|
446 |
-
}
|
447 |
-
}
|
448 |
-
}
|
449 |
-
}
|
450 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Awesome Motive Notifications
|
5 |
+
*
|
6 |
+
* This creates a custom post type (if it doesn't exist) and calls the API to
|
7 |
+
* retrieve notifications for this product.
|
8 |
+
*
|
9 |
+
* @package AwesomeMotive
|
10 |
+
* @author Benjamin Rojas
|
11 |
+
* @license GPL-2.0+
|
12 |
+
* @copyright Copyright (c) 2017, Retyp LLC
|
13 |
+
* @version 1.0.2
|
14 |
+
*/
|
15 |
+
class WPMS_AM_Notification {
|
16 |
+
/**
|
17 |
+
* The api url we are calling.
|
18 |
+
*
|
19 |
+
* @since 1.0.0
|
20 |
+
*
|
21 |
+
* @var string
|
22 |
+
*/
|
23 |
+
public $api_url = 'https://api.awesomemotive.com/v1/notification/';
|
24 |
+
|
25 |
+
/**
|
26 |
+
* A unique slug for this plugin.
|
27 |
+
* (Not the WordPress plugin slug)
|
28 |
+
*
|
29 |
+
* @since 1.0.0
|
30 |
+
*
|
31 |
+
* @var string
|
32 |
+
*/
|
33 |
+
public $plugin;
|
34 |
+
|
35 |
+
/**
|
36 |
+
* The current plugin version.
|
37 |
+
*
|
38 |
+
* @since 1.0.0
|
39 |
+
*
|
40 |
+
* @var string
|
41 |
+
*/
|
42 |
+
public $plugin_version;
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Flag if a notice has been registered.
|
46 |
+
*
|
47 |
+
* @since 1.0.0
|
48 |
+
*
|
49 |
+
* @var bool
|
50 |
+
*/
|
51 |
+
public static $registered = false;
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Construct.
|
55 |
+
*
|
56 |
+
* @since 1.0.0
|
57 |
+
*
|
58 |
+
* @param string $plugin The plugin slug.
|
59 |
+
* @param mixed $version The version of the plugin.
|
60 |
+
*/
|
61 |
+
public function __construct( $plugin = '', $version = 0 ) {
|
62 |
+
$this->plugin = $plugin;
|
63 |
+
$this->plugin_version = $version;
|
64 |
+
|
65 |
+
add_action( 'init', array( $this, 'custom_post_type' ) );
|
66 |
+
add_action( 'admin_init', array( $this, 'get_remote_notifications' ), 100 );
|
67 |
+
add_action( 'admin_notices', array( $this, 'display_notifications' ) );
|
68 |
+
add_action( 'wp_ajax_am_notification_dismiss', array( $this, 'dismiss_notification' ) );
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Registers a custom post type.
|
73 |
+
*
|
74 |
+
* @since 1.0.0
|
75 |
+
*/
|
76 |
+
public function custom_post_type() {
|
77 |
+
register_post_type( 'amn_' . $this->plugin, array(
|
78 |
+
'label' => $this->plugin . ' Announcements',
|
79 |
+
'can_export' => false,
|
80 |
+
'supports' => false,
|
81 |
+
) );
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Retrieve the remote notifications if the time has expired.
|
86 |
+
*
|
87 |
+
* @since 1.0.0
|
88 |
+
*/
|
89 |
+
public function get_remote_notifications() {
|
90 |
+
if ( ! current_user_can( apply_filters( 'am_notifications_display', 'manage_options' ) ) ) {
|
91 |
+
return;
|
92 |
+
}
|
93 |
+
|
94 |
+
$last_checked = get_option( '_amn_' . $this->plugin . '_last_checked', strtotime( '-1 week' ) );
|
95 |
+
|
96 |
+
if ( $last_checked < strtotime( 'today midnight' ) ) {
|
97 |
+
$plugin_notifications = $this->get_plugin_notifications( 1 );
|
98 |
+
$notification_id = null;
|
99 |
+
|
100 |
+
if ( ! empty( $plugin_notifications ) ) {
|
101 |
+
// Unset it from the array.
|
102 |
+
$notification = $plugin_notifications[0];
|
103 |
+
$notification_id = get_post_meta( $notification->ID, 'notification_id', true );
|
104 |
+
}
|
105 |
+
|
106 |
+
$response = wp_remote_retrieve_body( wp_remote_post( $this->api_url, array(
|
107 |
+
'body' => array(
|
108 |
+
'slug' => $this->plugin,
|
109 |
+
'version' => $this->plugin_version,
|
110 |
+
'last_notification' => $notification_id,
|
111 |
+
),
|
112 |
+
) ) );
|
113 |
+
|
114 |
+
$data = json_decode( $response );
|
115 |
+
|
116 |
+
if ( ! empty( $data->id ) ) {
|
117 |
+
$notifications = array();
|
118 |
+
|
119 |
+
foreach ( (array) $data->slugs as $slug ) {
|
120 |
+
$notifications = array_merge(
|
121 |
+
$notifications,
|
122 |
+
(array) get_posts(
|
123 |
+
array(
|
124 |
+
'post_type' => 'amn_' . $slug,
|
125 |
+
'post_status' => 'all',
|
126 |
+
'meta_key' => 'notification_id',
|
127 |
+
'meta_value' => $data->id,
|
128 |
+
)
|
129 |
+
)
|
130 |
+
);
|
131 |
+
}
|
132 |
+
|
133 |
+
if ( empty( $notifications ) ) {
|
134 |
+
$new_notification_id = wp_insert_post( array(
|
135 |
+
'post_content' => wp_kses_post( $data->content ),
|
136 |
+
'post_type' => 'amn_' . $this->plugin,
|
137 |
+
) );
|
138 |
+
|
139 |
+
update_post_meta( $new_notification_id, 'notification_id', absint( $data->id ) );
|
140 |
+
update_post_meta( $new_notification_id, 'type', sanitize_text_field( trim( $data->type ) ) );
|
141 |
+
update_post_meta( $new_notification_id, 'dismissable', (bool) $data->dismissible ? 1 : 0 );
|
142 |
+
update_post_meta( $new_notification_id, 'location', function_exists( 'wp_json_encode' ) ? wp_json_encode( $data->location ) : json_encode( $data->location ) );
|
143 |
+
update_post_meta( $new_notification_id, 'version', sanitize_text_field( trim( $data->version ) ) );
|
144 |
+
update_post_meta( $new_notification_id, 'viewed', 0 );
|
145 |
+
update_post_meta( $new_notification_id, 'expiration', $data->expiration ? absint( $data->expiration ) : false );
|
146 |
+
update_post_meta( $new_notification_id, 'plans', function_exists( 'wp_json_encode' ) ? wp_json_encode( $data->plans ) : json_encode( $data->plans ) );
|
147 |
+
}
|
148 |
+
}
|
149 |
+
|
150 |
+
// Possibly revoke notifications.
|
151 |
+
if ( ! empty( $data->revoked ) ) {
|
152 |
+
$this->revoke_notifications( $data->revoked );
|
153 |
+
}
|
154 |
+
|
155 |
+
// Set the option now so we can't run this again until after 24 hours.
|
156 |
+
update_option( '_amn_' . $this->plugin . '_last_checked', strtotime( 'today midnight' ) );
|
157 |
+
}
|
158 |
+
}
|
159 |
+
|
160 |
+
/**
|
161 |
+
* Get local plugin notifications that have already been set.
|
162 |
+
*
|
163 |
+
* @since 1.0.0
|
164 |
+
*
|
165 |
+
* @param integer $limit Set the limit for how many posts to retrieve.
|
166 |
+
* @param array $args Any top-level arguments to add to the array.
|
167 |
+
*
|
168 |
+
* @return WP_Post[] WP_Post that match the query.
|
169 |
+
*/
|
170 |
+
public function get_plugin_notifications( $limit = -1, $args = array() ) {
|
171 |
+
return get_posts(
|
172 |
+
array(
|
173 |
+
'posts_per_page' => $limit,
|
174 |
+
'post_type' => 'amn_' . $this->plugin,
|
175 |
+
) + $args
|
176 |
+
);
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* Display any notifications that should be displayed.
|
181 |
+
*
|
182 |
+
* @since 1.0.0
|
183 |
+
*/
|
184 |
+
public function display_notifications() {
|
185 |
+
if ( ! current_user_can( apply_filters( 'am_notifications_display', 'manage_options' ) ) ) {
|
186 |
+
return;
|
187 |
+
}
|
188 |
+
|
189 |
+
$plugin_notifications = $this->get_plugin_notifications( -1, array(
|
190 |
+
'post_status' => 'all',
|
191 |
+
'meta_key' => 'viewed',
|
192 |
+
'meta_value' => '0',
|
193 |
+
) );
|
194 |
+
|
195 |
+
$plugin_notifications = $this->validate_notifications( $plugin_notifications );
|
196 |
+
|
197 |
+
if ( ! empty( $plugin_notifications ) && ! self::$registered ) {
|
198 |
+
foreach ( $plugin_notifications as $notification ) {
|
199 |
+
$dismissable = get_post_meta( $notification->ID, 'dismissable', true );
|
200 |
+
$type = get_post_meta( $notification->ID, 'type', true );
|
201 |
+
?>
|
202 |
+
<div class="am-notification am-notification-<?php echo $notification->ID; ?> notice notice-<?php echo $type; ?><?php echo $dismissable ? ' is-dismissible' : ''; ?>">
|
203 |
+
<?php echo $notification->post_content; ?>
|
204 |
+
</div>
|
205 |
+
<script type="text/javascript">
|
206 |
+
jQuery(document).ready(function ($) {
|
207 |
+
$(document).on('click', '.am-notification-<?php echo $notification->ID; ?> button.notice-dismiss', function (event) {
|
208 |
+
$.post(ajaxurl, {
|
209 |
+
action: 'am_notification_dismiss',
|
210 |
+
notification_id: '<?php echo $notification->ID; ?>'
|
211 |
+
});
|
212 |
+
});
|
213 |
+
});
|
214 |
+
</script>
|
215 |
+
<?php
|
216 |
+
}
|
217 |
+
|
218 |
+
self::$registered = true;
|
219 |
+
}
|
220 |
+
}
|
221 |
+
|
222 |
+
/**
|
223 |
+
* Validate the notifications before displaying them.
|
224 |
+
*
|
225 |
+
* @since 1.0.0
|
226 |
+
*
|
227 |
+
* @param array $plugin_notifications An array of plugin notifications.
|
228 |
+
*
|
229 |
+
* @return array A filtered array of plugin notifications.
|
230 |
+
*/
|
231 |
+
public function validate_notifications( $plugin_notifications ) {
|
232 |
+
global $pagenow;
|
233 |
+
|
234 |
+
foreach ( $plugin_notifications as $key => $notification ) {
|
235 |
+
// Location validation.
|
236 |
+
$location = (array) json_decode( get_post_meta( $notification->ID, 'location', true ) );
|
237 |
+
$continue = false;
|
238 |
+
if ( ! in_array( 'everywhere', $location, true ) ) {
|
239 |
+
if ( in_array( 'index.php', $location, true ) && 'index.php' === $pagenow ) {
|
240 |
+
$continue = true;
|
241 |
+
}
|
242 |
+
|
243 |
+
if ( in_array( 'plugins.php', $location, true ) && 'plugins.php' === $pagenow ) {
|
244 |
+
$continue = true;
|
245 |
+
}
|
246 |
+
|
247 |
+
if ( ! $continue ) {
|
248 |
+
unset( $plugin_notifications[ $key ] );
|
249 |
+
}
|
250 |
+
}
|
251 |
+
|
252 |
+
// Plugin validation (OR conditional).
|
253 |
+
$plugins = (array) json_decode( get_post_meta( $notification->ID, 'plugins', true ) );
|
254 |
+
$continue = false;
|
255 |
+
if ( ! empty( $plugins ) ) {
|
256 |
+
foreach ( $plugins as $plugin ) {
|
257 |
+
if ( is_plugin_active( $plugin ) ) {
|
258 |
+
$continue = true;
|
259 |
+
}
|
260 |
+
}
|
261 |
+
|
262 |
+
if ( ! $continue ) {
|
263 |
+
unset( $plugin_notifications[ $key ] );
|
264 |
+
}
|
265 |
+
}
|
266 |
+
|
267 |
+
// Theme validation.
|
268 |
+
$theme = get_post_meta( $notification->ID, 'theme', true );
|
269 |
+
$continue = (string) wp_get_theme() === $theme;
|
270 |
+
|
271 |
+
if ( ! empty( $theme ) && ! $continue ) {
|
272 |
+
unset( $plugin_notifications[ $key ] );
|
273 |
+
}
|
274 |
+
|
275 |
+
// Version validation.
|
276 |
+
$version = get_post_meta( $notification->ID, 'version', true );
|
277 |
+
$continue = false;
|
278 |
+
if ( ! empty( $version ) ) {
|
279 |
+
if ( version_compare( $this->plugin_version, $version, '<=' ) ) {
|
280 |
+
$continue = true;
|
281 |
+
}
|
282 |
+
|
283 |
+
if ( ! $continue ) {
|
284 |
+
unset( $plugin_notifications[ $key ] );
|
285 |
+
}
|
286 |
+
}
|
287 |
+
|
288 |
+
// Expiration validation.
|
289 |
+
$expiration = get_post_meta( $notification->ID, 'expiration', true );
|
290 |
+
$continue = false;
|
291 |
+
if ( ! empty( $expiration ) ) {
|
292 |
+
if ( $expiration > time() ) {
|
293 |
+
$continue = true;
|
294 |
+
}
|
295 |
+
|
296 |
+
if ( ! $continue ) {
|
297 |
+
unset( $plugin_notifications[ $key ] );
|
298 |
+
}
|
299 |
+
}
|
300 |
+
|
301 |
+
// Plan validation.
|
302 |
+
$plans = (array) json_decode( get_post_meta( $notification->ID, 'plans', true ) );
|
303 |
+
$continue = false;
|
304 |
+
if ( ! empty( $plans ) ) {
|
305 |
+
$level = $this->get_plan_level();
|
306 |
+
if ( in_array( $level, $plans, true ) ) {
|
307 |
+
$continue = true;
|
308 |
+
}
|
309 |
+
|
310 |
+
if ( ! $continue ) {
|
311 |
+
unset( $plugin_notifications[ $key ] );
|
312 |
+
}
|
313 |
+
}
|
314 |
+
}
|
315 |
+
|
316 |
+
return $plugin_notifications;
|
317 |
+
}
|
318 |
+
|
319 |
+
/**
|
320 |
+
* Grab the current plan level.
|
321 |
+
*
|
322 |
+
* @since 1.0.0
|
323 |
+
*
|
324 |
+
* @return string The current plan level.
|
325 |
+
*/
|
326 |
+
public function get_plan_level() {
|
327 |
+
// Prepare variables.
|
328 |
+
$key = '';
|
329 |
+
$level = '';
|
330 |
+
$option = false;
|
331 |
+
switch ( $this->plugin ) {
|
332 |
+
case 'wpforms' :
|
333 |
+
$option = get_option( 'wpforms_license' );
|
334 |
+
$key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
|
335 |
+
$level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
|
336 |
+
|
337 |
+
// Possibly check for a constant.
|
338 |
+
if ( empty( $key ) && defined( 'WPFORMS_LICENSE_KEY' ) ) {
|
339 |
+
$key = WPFORMS_LICENSE_KEY;
|
340 |
+
}
|
341 |
+
break;
|
342 |
+
case 'mi' :
|
343 |
+
$option = get_option( 'monsterinsights_license' );
|
344 |
+
$key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
|
345 |
+
$level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
|
346 |
+
|
347 |
+
// Possibly check for a constant.
|
348 |
+
if ( empty( $key ) && defined( 'MONSTERINSIGHTS_LICENSE_KEY' ) && is_string( MONSTERINSIGHTS_LICENSE_KEY ) && strlen( MONSTERINSIGHTS_LICENSE_KEY ) > 10 ) {
|
349 |
+
$key = MONSTERINSIGHTS_LICENSE_KEY;
|
350 |
+
}
|
351 |
+
break;
|
352 |
+
case 'sol' :
|
353 |
+
$option = get_option( 'soliloquy' );
|
354 |
+
$key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
|
355 |
+
$level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
|
356 |
+
|
357 |
+
// Possibly check for a constant.
|
358 |
+
if ( empty( $key ) && defined( 'SOLILOQUY_LICENSE_KEY' ) ) {
|
359 |
+
$key = SOLILOQUY_LICENSE_KEY;
|
360 |
+
}
|
361 |
+
break;
|
362 |
+
case 'envira' :
|
363 |
+
$option = get_option( 'envira_gallery' );
|
364 |
+
$key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
|
365 |
+
$level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
|
366 |
+
|
367 |
+
// Possibly check for a constant.
|
368 |
+
if ( empty( $key ) && defined( 'ENVIRA_LICENSE_KEY' ) ) {
|
369 |
+
$key = ENVIRA_LICENSE_KEY;
|
370 |
+
}
|
371 |
+
break;
|
372 |
+
case 'om' :
|
373 |
+
$option = get_option( 'optin_monster_api' );
|
374 |
+
$key = is_array( $option ) && isset( $option['api']['apikey'] ) ? $option['api']['apikey'] : '';
|
375 |
+
|
376 |
+
// Possibly check for a constant.
|
377 |
+
if ( empty( $key ) && defined( 'OPTINMONSTER_REST_API_LICENSE_KEY' ) ) {
|
378 |
+
$key = OPTINMONSTER_REST_API_LICENSE_KEY;
|
379 |
+
}
|
380 |
+
|
381 |
+
// If the key is still empty, check for the old legacy key.
|
382 |
+
if ( empty( $key ) ) {
|
383 |
+
$key = is_array( $option ) && isset( $option['api']['key'] ) ? $option['api']['key'] : '';
|
384 |
+
}
|
385 |
+
break;
|
386 |
+
}
|
387 |
+
|
388 |
+
// Possibly set the level to 'none' if the key is empty and no level has been set.
|
389 |
+
if ( empty( $key ) && empty( $level ) ) {
|
390 |
+
$level = 'none';
|
391 |
+
}
|
392 |
+
|
393 |
+
// Normalize the level.
|
394 |
+
switch ( $level ) {
|
395 |
+
case 'bronze' :
|
396 |
+
case 'personal' :
|
397 |
+
$level = 'basic';
|
398 |
+
break;
|
399 |
+
case 'silver' :
|
400 |
+
case 'multi' :
|
401 |
+
$level = 'plus';
|
402 |
+
break;
|
403 |
+
case 'gold' :
|
404 |
+
case 'developer' :
|
405 |
+
$level = 'pro';
|
406 |
+
break;
|
407 |
+
case 'platinum' :
|
408 |
+
case 'master' :
|
409 |
+
$level = 'ultimate';
|
410 |
+
break;
|
411 |
+
}
|
412 |
+
|
413 |
+
// Return the plan level.
|
414 |
+
return $level;
|
415 |
+
}
|
416 |
+
|
417 |
+
/**
|
418 |
+
* Dismiss the notification via AJAX.
|
419 |
+
*
|
420 |
+
* @since 1.0.0
|
421 |
+
*/
|
422 |
+
public function dismiss_notification() {
|
423 |
+
if ( ! current_user_can( apply_filters( 'am_notifications_display', 'manage_options' ) ) ) {
|
424 |
+
die;
|
425 |
+
}
|
426 |
+
|
427 |
+
$notification_id = intval( $_POST['notification_id'] );
|
428 |
+
update_post_meta( $notification_id, 'viewed', 1 );
|
429 |
+
die;
|
430 |
+
}
|
431 |
+
|
432 |
+
/**
|
433 |
+
* Revokes notifications.
|
434 |
+
*
|
435 |
+
* @since 1.0.0
|
436 |
+
*
|
437 |
+
* @param array $ids An array of notification IDs to revoke.
|
438 |
+
*/
|
439 |
+
public function revoke_notifications( $ids ) {
|
440 |
+
// Loop through each of the IDs and find the post that has it as meta.
|
441 |
+
foreach ( (array) $ids as $id ) {
|
442 |
+
$notifications = $this->get_plugin_notifications( -1, array( 'post_status' => 'all', 'meta_key' => 'notification_id', 'meta_value' => $id ) );
|
443 |
+
if ( $notifications ) {
|
444 |
+
foreach ( $notifications as $notification ) {
|
445 |
+
update_post_meta( $notification->ID, 'viewed', 1 );
|
446 |
+
}
|
447 |
+
}
|
448 |
+
}
|
449 |
+
}
|
450 |
+
}
|
languages/wp-mail-smtp.pot
CHANGED
@@ -142,11 +142,11 @@ msgstr ""
|
|
142 |
msgid "Use TLS encryption."
|
143 |
msgstr ""
|
144 |
|
145 |
-
#: wp_mail_smtp.php:462
|
146 |
msgid "TLS is not the same as STARTTLS. For most servers SSL is the recommended option."
|
147 |
msgstr ""
|
148 |
|
149 |
-
#: wp_mail_smtp.php:467, wp_mail_smtp.php:471, src/Providers/OptionAbstract.php:
|
150 |
msgid "Authentication"
|
151 |
msgstr ""
|
152 |
|
@@ -238,31 +238,43 @@ msgstr ""
|
|
238 |
msgid "TLS"
|
239 |
msgstr ""
|
240 |
|
241 |
-
#: src/Providers/OptionAbstract.php:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
242 |
msgid "On"
|
243 |
msgstr ""
|
244 |
|
245 |
-
#: src/Providers/OptionAbstract.php:
|
246 |
msgid "Off"
|
247 |
msgstr ""
|
248 |
|
249 |
-
#: src/Providers/OptionAbstract.php:
|
|
|
|
|
|
|
|
|
250 |
msgid "SMTP Username"
|
251 |
msgstr ""
|
252 |
|
253 |
-
#: src/Providers/OptionAbstract.php:
|
254 |
msgid "SMTP Password"
|
255 |
msgstr ""
|
256 |
|
257 |
-
#: src/Providers/OptionAbstract.php:
|
258 |
msgid "The password is stored in plain text. We highly recommend you setup your password in your WordPress configuration file for improved security; to do this add the lines below to your %s file."
|
259 |
msgstr ""
|
260 |
|
261 |
-
#: src/Providers/OptionAbstract.php:
|
262 |
msgid "%1$s requires PHP %2$s to work and does not support your current PHP version %3$s. Please contact your host and request a PHP upgrade to the latest one."
|
263 |
msgstr ""
|
264 |
|
265 |
-
#: src/Providers/OptionAbstract.php:
|
266 |
msgid "Meanwhile you can switch to the \"Other SMTP\" Mailer option."
|
267 |
msgstr ""
|
268 |
|
@@ -350,6 +362,10 @@ msgstr ""
|
|
350 |
msgid "The related debugging output is shown below:"
|
351 |
msgstr ""
|
352 |
|
|
|
|
|
|
|
|
|
353 |
#: src/Providers/Gmail/Options.php:25
|
354 |
msgid "Gmail"
|
355 |
msgstr ""
|
142 |
msgid "Use TLS encryption."
|
143 |
msgstr ""
|
144 |
|
145 |
+
#: wp_mail_smtp.php:462
|
146 |
msgid "TLS is not the same as STARTTLS. For most servers SSL is the recommended option."
|
147 |
msgstr ""
|
148 |
|
149 |
+
#: wp_mail_smtp.php:467, wp_mail_smtp.php:471, src/Providers/OptionAbstract.php:216
|
150 |
msgid "Authentication"
|
151 |
msgstr ""
|
152 |
|
238 |
msgid "TLS"
|
239 |
msgstr ""
|
240 |
|
241 |
+
#: src/Providers/OptionAbstract.php:186
|
242 |
+
msgid "For most servers TLS is the recommended option. If your SMTP provider offers both SSL and TLS options, we recommend using TLS."
|
243 |
+
msgstr ""
|
244 |
+
|
245 |
+
#: src/Providers/OptionAbstract.php:194
|
246 |
+
msgid "Auto TLS"
|
247 |
+
msgstr ""
|
248 |
+
|
249 |
+
#: src/Providers/OptionAbstract.php:204, src/Providers/OptionAbstract.php:226
|
250 |
msgid "On"
|
251 |
msgstr ""
|
252 |
|
253 |
+
#: src/Providers/OptionAbstract.php:205, src/Providers/OptionAbstract.php:227
|
254 |
msgid "Off"
|
255 |
msgstr ""
|
256 |
|
257 |
+
#: src/Providers/OptionAbstract.php:208
|
258 |
+
msgid "By default TLS encryption is automatically used if the server supports it, which is recommended. In some cases, due to server misconfigurations, this can cause issues and may need to be disabled."
|
259 |
+
msgstr ""
|
260 |
+
|
261 |
+
#: src/Providers/OptionAbstract.php:235
|
262 |
msgid "SMTP Username"
|
263 |
msgstr ""
|
264 |
|
265 |
+
#: src/Providers/OptionAbstract.php:249
|
266 |
msgid "SMTP Password"
|
267 |
msgstr ""
|
268 |
|
269 |
+
#: src/Providers/OptionAbstract.php:263
|
270 |
msgid "The password is stored in plain text. We highly recommend you setup your password in your WordPress configuration file for improved security; to do this add the lines below to your %s file."
|
271 |
msgstr ""
|
272 |
|
273 |
+
#: src/Providers/OptionAbstract.php:300
|
274 |
msgid "%1$s requires PHP %2$s to work and does not support your current PHP version %3$s. Please contact your host and request a PHP upgrade to the latest one."
|
275 |
msgstr ""
|
276 |
|
277 |
+
#: src/Providers/OptionAbstract.php:307
|
278 |
msgid "Meanwhile you can switch to the \"Other SMTP\" Mailer option."
|
279 |
msgstr ""
|
280 |
|
362 |
msgid "The related debugging output is shown below:"
|
363 |
msgstr ""
|
364 |
|
365 |
+
#: src/Admin/Pages/Test.php:136
|
366 |
+
msgid "Please copy only the content of the error debug message above, identified with an orange left border, into the support forum topic if you experience any issues."
|
367 |
+
msgstr ""
|
368 |
+
|
369 |
#: src/Providers/Gmail/Options.php:25
|
370 |
msgid "Gmail"
|
371 |
msgstr ""
|
readme.txt
CHANGED
@@ -146,6 +146,16 @@ By all means please contact us to discuss features or options you'd like to see
|
|
146 |
|
147 |
== Changelog ==
|
148 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
149 |
= 1.0.2 - 2017-12-12 =
|
150 |
* Fixed: PHPMailer using incorrect SMTPSecure value.
|
151 |
|
146 |
|
147 |
== Changelog ==
|
148 |
|
149 |
+
= 1.1.0 - 2017-12-18 =
|
150 |
+
* Added: New option "Auto TLS" for SMTP mailer. Default is enabled. Migration routine for all sites.
|
151 |
+
* Changed: Improve debug output - clear styles and context-aware content.
|
152 |
+
* Changed: Better exceptions handling for Google authentication process.
|
153 |
+
* Changed: Do not sanitize passwords, api keys etc - as they may contain special characters in certain order and sanitization will break those values.
|
154 |
+
* Changed: Improve wording of some helpful texts inside plugin admin area.
|
155 |
+
* Fixed: Do not include certain files in dependency libraries that are not used by Google mailer. This should stop flagging plugin by Wordfence and VaultPress.
|
156 |
+
* Fixed: Constants usage is working now, to define the SMTP password, for example.
|
157 |
+
* Fixed: Notice for default mailer.
|
158 |
+
|
159 |
= 1.0.2 - 2017-12-12 =
|
160 |
* Fixed: PHPMailer using incorrect SMTPSecure value.
|
161 |
|
src/AM_Notification.php
CHANGED
@@ -1,452 +1,452 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Awesome Motive Notifications
|
7 |
-
*
|
8 |
-
* This creates a custom post type (if it doesn't exist) and calls the API to
|
9 |
-
* retrieve notifications for this product.
|
10 |
-
*
|
11 |
-
* @package AwesomeMotive
|
12 |
-
* @author Benjamin Rojas
|
13 |
-
* @license GPL-2.0+
|
14 |
-
* @copyright Copyright (c) 2017, Retyp LLC
|
15 |
-
* @version 1.0.2
|
16 |
-
*/
|
17 |
-
class AM_Notification {
|
18 |
-
/**
|
19 |
-
* The api url we are calling.
|
20 |
-
*
|
21 |
-
* @since 1.0.0
|
22 |
-
*
|
23 |
-
* @var string
|
24 |
-
*/
|
25 |
-
public $api_url = 'https://api.awesomemotive.com/v1/notification/';
|
26 |
-
|
27 |
-
/**
|
28 |
-
* A unique slug for this plugin.
|
29 |
-
* (Not the WordPress plugin slug)
|
30 |
-
*
|
31 |
-
* @since 1.0.0
|
32 |
-
*
|
33 |
-
* @var string
|
34 |
-
*/
|
35 |
-
public $plugin;
|
36 |
-
|
37 |
-
/**
|
38 |
-
* The current plugin version.
|
39 |
-
*
|
40 |
-
* @since 1.0.0
|
41 |
-
*
|
42 |
-
* @var string
|
43 |
-
*/
|
44 |
-
public $plugin_version;
|
45 |
-
|
46 |
-
/**
|
47 |
-
* Flag if a notice has been registered.
|
48 |
-
*
|
49 |
-
* @since 1.0.0
|
50 |
-
*
|
51 |
-
* @var bool
|
52 |
-
*/
|
53 |
-
public static $registered = false;
|
54 |
-
|
55 |
-
/**
|
56 |
-
* Construct.
|
57 |
-
*
|
58 |
-
* @since 1.0.0
|
59 |
-
*
|
60 |
-
* @param string $plugin The plugin slug.
|
61 |
-
* @param mixed $version The version of the plugin.
|
62 |
-
*/
|
63 |
-
public function __construct( $plugin = '', $version = 0 ) {
|
64 |
-
$this->plugin = $plugin;
|
65 |
-
$this->plugin_version = $version;
|
66 |
-
|
67 |
-
add_action( 'init', array( $this, 'custom_post_type' ) );
|
68 |
-
add_action( 'admin_init', array( $this, 'get_remote_notifications' ), 100 );
|
69 |
-
add_action( 'admin_notices', array( $this, 'display_notifications' ) );
|
70 |
-
add_action( 'wp_ajax_am_notification_dismiss', array( $this, 'dismiss_notification' ) );
|
71 |
-
}
|
72 |
-
|
73 |
-
/**
|
74 |
-
* Registers a custom post type.
|
75 |
-
*
|
76 |
-
* @since 1.0.0
|
77 |
-
*/
|
78 |
-
public function custom_post_type() {
|
79 |
-
register_post_type( 'amn_' . $this->plugin, array(
|
80 |
-
'label' => $this->plugin . ' Announcements',
|
81 |
-
'can_export' => false,
|
82 |
-
'supports' => false,
|
83 |
-
) );
|
84 |
-
}
|
85 |
-
|
86 |
-
/**
|
87 |
-
* Retrieve the remote notifications if the time has expired.
|
88 |
-
*
|
89 |
-
* @since 1.0.0
|
90 |
-
*/
|
91 |
-
public function get_remote_notifications() {
|
92 |
-
if ( ! current_user_can( apply_filters( 'am_notifications_display', 'manage_options' ) ) ) {
|
93 |
-
return;
|
94 |
-
}
|
95 |
-
|
96 |
-
$last_checked = get_option( '_amn_' . $this->plugin . '_last_checked', strtotime( '-1 week' ) );
|
97 |
-
|
98 |
-
if ( $last_checked < strtotime( 'today midnight' ) ) {
|
99 |
-
$plugin_notifications = $this->get_plugin_notifications( 1 );
|
100 |
-
$notification_id = null;
|
101 |
-
|
102 |
-
if ( ! empty( $plugin_notifications ) ) {
|
103 |
-
// Unset it from the array.
|
104 |
-
$notification = $plugin_notifications[0];
|
105 |
-
$notification_id = get_post_meta( $notification->ID, 'notification_id', true );
|
106 |
-
}
|
107 |
-
|
108 |
-
$response = wp_remote_retrieve_body( wp_remote_post( $this->api_url, array(
|
109 |
-
'body' => array(
|
110 |
-
'slug' => $this->plugin,
|
111 |
-
'version' => $this->plugin_version,
|
112 |
-
'last_notification' => $notification_id,
|
113 |
-
),
|
114 |
-
) ) );
|
115 |
-
|
116 |
-
$data = json_decode( $response );
|
117 |
-
|
118 |
-
if ( ! empty( $data->id ) ) {
|
119 |
-
$notifications = array();
|
120 |
-
|
121 |
-
foreach ( (array) $data->slugs as $slug ) {
|
122 |
-
$notifications = array_merge(
|
123 |
-
$notifications,
|
124 |
-
(array) get_posts(
|
125 |
-
array(
|
126 |
-
'post_type' => 'amn_' . $slug,
|
127 |
-
'post_status' => 'all',
|
128 |
-
'meta_key' => 'notification_id',
|
129 |
-
'meta_value' => $data->id,
|
130 |
-
)
|
131 |
-
)
|
132 |
-
);
|
133 |
-
}
|
134 |
-
|
135 |
-
if ( empty( $notifications ) ) {
|
136 |
-
$new_notification_id = wp_insert_post( array(
|
137 |
-
'post_content' => wp_kses_post( $data->content ),
|
138 |
-
'post_type' => 'amn_' . $this->plugin,
|
139 |
-
) );
|
140 |
-
|
141 |
-
update_post_meta( $new_notification_id, 'notification_id', absint( $data->id ) );
|
142 |
-
update_post_meta( $new_notification_id, 'type', sanitize_text_field( trim( $data->type ) ) );
|
143 |
-
update_post_meta( $new_notification_id, 'dismissable', (bool) $data->dismissible ? 1 : 0 );
|
144 |
-
update_post_meta( $new_notification_id, 'location', function_exists( 'wp_json_encode' ) ? wp_json_encode( $data->location ) : json_encode( $data->location ) );
|
145 |
-
update_post_meta( $new_notification_id, 'version', sanitize_text_field( trim( $data->version ) ) );
|
146 |
-
update_post_meta( $new_notification_id, 'viewed', 0 );
|
147 |
-
update_post_meta( $new_notification_id, 'expiration', $data->expiration ? absint( $data->expiration ) : false );
|
148 |
-
update_post_meta( $new_notification_id, 'plans', function_exists( 'wp_json_encode' ) ? wp_json_encode( $data->plans ) : json_encode( $data->plans ) );
|
149 |
-
}
|
150 |
-
}
|
151 |
-
|
152 |
-
// Possibly revoke notifications.
|
153 |
-
if ( ! empty( $data->revoked ) ) {
|
154 |
-
$this->revoke_notifications( $data->revoked );
|
155 |
-
}
|
156 |
-
|
157 |
-
// Set the option now so we can't run this again until after 24 hours.
|
158 |
-
update_option( '_amn_' . $this->plugin . '_last_checked', strtotime( 'today midnight' ) );
|
159 |
-
}
|
160 |
-
}
|
161 |
-
|
162 |
-
/**
|
163 |
-
* Get local plugin notifications that have already been set.
|
164 |
-
*
|
165 |
-
* @since 1.0.0
|
166 |
-
*
|
167 |
-
* @param integer $limit Set the limit for how many posts to retrieve.
|
168 |
-
* @param array $args Any top-level arguments to add to the array.
|
169 |
-
*
|
170 |
-
* @return WP_Post[] WP_Post that match the query.
|
171 |
-
*/
|
172 |
-
public function get_plugin_notifications( $limit = -1, $args = array() ) {
|
173 |
-
return get_posts(
|
174 |
-
array(
|
175 |
-
'posts_per_page' => $limit,
|
176 |
-
'post_type' => 'amn_' . $this->plugin,
|
177 |
-
) + $args
|
178 |
-
);
|
179 |
-
}
|
180 |
-
|
181 |
-
/**
|
182 |
-
* Display any notifications that should be displayed.
|
183 |
-
*
|
184 |
-
* @since 1.0.0
|
185 |
-
*/
|
186 |
-
public function display_notifications() {
|
187 |
-
if ( ! current_user_can( apply_filters( 'am_notifications_display', 'manage_options' ) ) ) {
|
188 |
-
return;
|
189 |
-
}
|
190 |
-
|
191 |
-
$plugin_notifications = $this->get_plugin_notifications( -1, array(
|
192 |
-
'post_status' => 'all',
|
193 |
-
'meta_key' => 'viewed',
|
194 |
-
'meta_value' => '0',
|
195 |
-
) );
|
196 |
-
|
197 |
-
$plugin_notifications = $this->validate_notifications( $plugin_notifications );
|
198 |
-
|
199 |
-
if ( ! empty( $plugin_notifications ) && ! self::$registered ) {
|
200 |
-
foreach ( $plugin_notifications as $notification ) {
|
201 |
-
$dismissable = get_post_meta( $notification->ID, 'dismissable', true );
|
202 |
-
$type = get_post_meta( $notification->ID, 'type', true );
|
203 |
-
?>
|
204 |
-
<div class="am-notification am-notification-<?php echo $notification->ID; ?> notice notice-<?php echo $type; ?><?php echo $dismissable ? ' is-dismissible' : ''; ?>">
|
205 |
-
<?php echo $notification->post_content; ?>
|
206 |
-
</div>
|
207 |
-
<script type="text/javascript">
|
208 |
-
jQuery(document).ready(function ($) {
|
209 |
-
$(document).on('click', '.am-notification-<?php echo $notification->ID; ?> button.notice-dismiss', function (event) {
|
210 |
-
$.post(ajaxurl, {
|
211 |
-
action: 'am_notification_dismiss',
|
212 |
-
notification_id: '<?php echo $notification->ID; ?>'
|
213 |
-
});
|
214 |
-
});
|
215 |
-
});
|
216 |
-
</script>
|
217 |
-
<?php
|
218 |
-
}
|
219 |
-
|
220 |
-
self::$registered = true;
|
221 |
-
}
|
222 |
-
}
|
223 |
-
|
224 |
-
/**
|
225 |
-
* Validate the notifications before displaying them.
|
226 |
-
*
|
227 |
-
* @since 1.0.0
|
228 |
-
*
|
229 |
-
* @param array $plugin_notifications An array of plugin notifications.
|
230 |
-
*
|
231 |
-
* @return array A filtered array of plugin notifications.
|
232 |
-
*/
|
233 |
-
public function validate_notifications( $plugin_notifications ) {
|
234 |
-
global $pagenow;
|
235 |
-
|
236 |
-
foreach ( $plugin_notifications as $key => $notification ) {
|
237 |
-
// Location validation.
|
238 |
-
$location = (array) json_decode( get_post_meta( $notification->ID, 'location', true ) );
|
239 |
-
$continue = false;
|
240 |
-
if ( ! in_array( 'everywhere', $location, true ) ) {
|
241 |
-
if ( in_array( 'index.php', $location, true ) && 'index.php' === $pagenow ) {
|
242 |
-
$continue = true;
|
243 |
-
}
|
244 |
-
|
245 |
-
if ( in_array( 'plugins.php', $location, true ) && 'plugins.php' === $pagenow ) {
|
246 |
-
$continue = true;
|
247 |
-
}
|
248 |
-
|
249 |
-
if ( ! $continue ) {
|
250 |
-
unset( $plugin_notifications[ $key ] );
|
251 |
-
}
|
252 |
-
}
|
253 |
-
|
254 |
-
// Plugin validation (OR conditional).
|
255 |
-
$plugins = (array) json_decode( get_post_meta( $notification->ID, 'plugins', true ) );
|
256 |
-
$continue = false;
|
257 |
-
if ( ! empty( $plugins ) ) {
|
258 |
-
foreach ( $plugins as $plugin ) {
|
259 |
-
if ( is_plugin_active( $plugin ) ) {
|
260 |
-
$continue = true;
|
261 |
-
}
|
262 |
-
}
|
263 |
-
|
264 |
-
if ( ! $continue ) {
|
265 |
-
unset( $plugin_notifications[ $key ] );
|
266 |
-
}
|
267 |
-
}
|
268 |
-
|
269 |
-
// Theme validation.
|
270 |
-
$theme = get_post_meta( $notification->ID, 'theme', true );
|
271 |
-
$continue = (string) wp_get_theme() === $theme;
|
272 |
-
|
273 |
-
if ( ! empty( $theme ) && ! $continue ) {
|
274 |
-
unset( $plugin_notifications[ $key ] );
|
275 |
-
}
|
276 |
-
|
277 |
-
// Version validation.
|
278 |
-
$version = get_post_meta( $notification->ID, 'version', true );
|
279 |
-
$continue = false;
|
280 |
-
if ( ! empty( $version ) ) {
|
281 |
-
if ( version_compare( $this->plugin_version, $version, '<=' ) ) {
|
282 |
-
$continue = true;
|
283 |
-
}
|
284 |
-
|
285 |
-
if ( ! $continue ) {
|
286 |
-
unset( $plugin_notifications[ $key ] );
|
287 |
-
}
|
288 |
-
}
|
289 |
-
|
290 |
-
// Expiration validation.
|
291 |
-
$expiration = get_post_meta( $notification->ID, 'expiration', true );
|
292 |
-
$continue = false;
|
293 |
-
if ( ! empty( $expiration ) ) {
|
294 |
-
if ( $expiration > time() ) {
|
295 |
-
$continue = true;
|
296 |
-
}
|
297 |
-
|
298 |
-
if ( ! $continue ) {
|
299 |
-
unset( $plugin_notifications[ $key ] );
|
300 |
-
}
|
301 |
-
}
|
302 |
-
|
303 |
-
// Plan validation.
|
304 |
-
$plans = (array) json_decode( get_post_meta( $notification->ID, 'plans', true ) );
|
305 |
-
$continue = false;
|
306 |
-
if ( ! empty( $plans ) ) {
|
307 |
-
$level = $this->get_plan_level();
|
308 |
-
if ( in_array( $level, $plans, true ) ) {
|
309 |
-
$continue = true;
|
310 |
-
}
|
311 |
-
|
312 |
-
if ( ! $continue ) {
|
313 |
-
unset( $plugin_notifications[ $key ] );
|
314 |
-
}
|
315 |
-
}
|
316 |
-
}
|
317 |
-
|
318 |
-
return $plugin_notifications;
|
319 |
-
}
|
320 |
-
|
321 |
-
/**
|
322 |
-
* Grab the current plan level.
|
323 |
-
*
|
324 |
-
* @since 1.0.0
|
325 |
-
*
|
326 |
-
* @return string The current plan level.
|
327 |
-
*/
|
328 |
-
public function get_plan_level() {
|
329 |
-
// Prepare variables.
|
330 |
-
$key = '';
|
331 |
-
$level = '';
|
332 |
-
$option = false;
|
333 |
-
switch ( $this->plugin ) {
|
334 |
-
case 'wpforms' :
|
335 |
-
$option = get_option( 'wpforms_license' );
|
336 |
-
$key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
|
337 |
-
$level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
|
338 |
-
|
339 |
-
// Possibly check for a constant.
|
340 |
-
if ( empty( $key ) && defined( 'WPFORMS_LICENSE_KEY' ) ) {
|
341 |
-
$key = WPFORMS_LICENSE_KEY;
|
342 |
-
}
|
343 |
-
break;
|
344 |
-
case 'mi' :
|
345 |
-
$option = get_option( 'monsterinsights_license' );
|
346 |
-
$key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
|
347 |
-
$level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
|
348 |
-
|
349 |
-
// Possibly check for a constant.
|
350 |
-
if ( empty( $key ) && defined( 'MONSTERINSIGHTS_LICENSE_KEY' ) && is_string( MONSTERINSIGHTS_LICENSE_KEY ) && strlen( MONSTERINSIGHTS_LICENSE_KEY ) > 10 ) {
|
351 |
-
$key = MONSTERINSIGHTS_LICENSE_KEY;
|
352 |
-
}
|
353 |
-
break;
|
354 |
-
case 'sol' :
|
355 |
-
$option = get_option( 'soliloquy' );
|
356 |
-
$key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
|
357 |
-
$level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
|
358 |
-
|
359 |
-
// Possibly check for a constant.
|
360 |
-
if ( empty( $key ) && defined( 'SOLILOQUY_LICENSE_KEY' ) ) {
|
361 |
-
$key = SOLILOQUY_LICENSE_KEY;
|
362 |
-
}
|
363 |
-
break;
|
364 |
-
case 'envira' :
|
365 |
-
$option = get_option( 'envira_gallery' );
|
366 |
-
$key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
|
367 |
-
$level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
|
368 |
-
|
369 |
-
// Possibly check for a constant.
|
370 |
-
if ( empty( $key ) && defined( 'ENVIRA_LICENSE_KEY' ) ) {
|
371 |
-
$key = ENVIRA_LICENSE_KEY;
|
372 |
-
}
|
373 |
-
break;
|
374 |
-
case 'om' :
|
375 |
-
$option = get_option( 'optin_monster_api' );
|
376 |
-
$key = is_array( $option ) && isset( $option['api']['apikey'] ) ? $option['api']['apikey'] : '';
|
377 |
-
|
378 |
-
// Possibly check for a constant.
|
379 |
-
if ( empty( $key ) && defined( 'OPTINMONSTER_REST_API_LICENSE_KEY' ) ) {
|
380 |
-
$key = OPTINMONSTER_REST_API_LICENSE_KEY;
|
381 |
-
}
|
382 |
-
|
383 |
-
// If the key is still empty, check for the old legacy key.
|
384 |
-
if ( empty( $key ) ) {
|
385 |
-
$key = is_array( $option ) && isset( $option['api']['key'] ) ? $option['api']['key'] : '';
|
386 |
-
}
|
387 |
-
break;
|
388 |
-
}
|
389 |
-
|
390 |
-
// Possibly set the level to 'none' if the key is empty and no level has been set.
|
391 |
-
if ( empty( $key ) && empty( $level ) ) {
|
392 |
-
$level = 'none';
|
393 |
-
}
|
394 |
-
|
395 |
-
// Normalize the level.
|
396 |
-
switch ( $level ) {
|
397 |
-
case 'bronze' :
|
398 |
-
case 'personal' :
|
399 |
-
$level = 'basic';
|
400 |
-
break;
|
401 |
-
case 'silver' :
|
402 |
-
case 'multi' :
|
403 |
-
$level = 'plus';
|
404 |
-
break;
|
405 |
-
case 'gold' :
|
406 |
-
case 'developer' :
|
407 |
-
$level = 'pro';
|
408 |
-
break;
|
409 |
-
case 'platinum' :
|
410 |
-
case 'master' :
|
411 |
-
$level = 'ultimate';
|
412 |
-
break;
|
413 |
-
}
|
414 |
-
|
415 |
-
// Return the plan level.
|
416 |
-
return $level;
|
417 |
-
}
|
418 |
-
|
419 |
-
/**
|
420 |
-
* Dismiss the notification via AJAX.
|
421 |
-
*
|
422 |
-
* @since 1.0.0
|
423 |
-
*/
|
424 |
-
public function dismiss_notification() {
|
425 |
-
if ( ! current_user_can( apply_filters( 'am_notifications_display', 'manage_options' ) ) ) {
|
426 |
-
die;
|
427 |
-
}
|
428 |
-
|
429 |
-
$notification_id = intval( $_POST['notification_id'] );
|
430 |
-
update_post_meta( $notification_id, 'viewed', 1 );
|
431 |
-
die;
|
432 |
-
}
|
433 |
-
|
434 |
-
/**
|
435 |
-
* Revokes notifications.
|
436 |
-
*
|
437 |
-
* @since 1.0.0
|
438 |
-
*
|
439 |
-
* @param array $ids An array of notification IDs to revoke.
|
440 |
-
*/
|
441 |
-
public function revoke_notifications( $ids ) {
|
442 |
-
// Loop through each of the IDs and find the post that has it as meta.
|
443 |
-
foreach ( (array) $ids as $id ) {
|
444 |
-
$notifications = $this->get_plugin_notifications( -1, array( 'post_status' => 'all', 'meta_key' => 'notification_id', 'meta_value' => $id ) );
|
445 |
-
if ( $notifications ) {
|
446 |
-
foreach ( $notifications as $notification ) {
|
447 |
-
update_post_meta( $notification->ID, 'viewed', 1 );
|
448 |
-
}
|
449 |
-
}
|
450 |
-
}
|
451 |
-
}
|
452 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Awesome Motive Notifications
|
7 |
+
*
|
8 |
+
* This creates a custom post type (if it doesn't exist) and calls the API to
|
9 |
+
* retrieve notifications for this product.
|
10 |
+
*
|
11 |
+
* @package AwesomeMotive
|
12 |
+
* @author Benjamin Rojas
|
13 |
+
* @license GPL-2.0+
|
14 |
+
* @copyright Copyright (c) 2017, Retyp LLC
|
15 |
+
* @version 1.0.2
|
16 |
+
*/
|
17 |
+
class AM_Notification {
|
18 |
+
/**
|
19 |
+
* The api url we are calling.
|
20 |
+
*
|
21 |
+
* @since 1.0.0
|
22 |
+
*
|
23 |
+
* @var string
|
24 |
+
*/
|
25 |
+
public $api_url = 'https://api.awesomemotive.com/v1/notification/';
|
26 |
+
|
27 |
+
/**
|
28 |
+
* A unique slug for this plugin.
|
29 |
+
* (Not the WordPress plugin slug)
|
30 |
+
*
|
31 |
+
* @since 1.0.0
|
32 |
+
*
|
33 |
+
* @var string
|
34 |
+
*/
|
35 |
+
public $plugin;
|
36 |
+
|
37 |
+
/**
|
38 |
+
* The current plugin version.
|
39 |
+
*
|
40 |
+
* @since 1.0.0
|
41 |
+
*
|
42 |
+
* @var string
|
43 |
+
*/
|
44 |
+
public $plugin_version;
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Flag if a notice has been registered.
|
48 |
+
*
|
49 |
+
* @since 1.0.0
|
50 |
+
*
|
51 |
+
* @var bool
|
52 |
+
*/
|
53 |
+
public static $registered = false;
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Construct.
|
57 |
+
*
|
58 |
+
* @since 1.0.0
|
59 |
+
*
|
60 |
+
* @param string $plugin The plugin slug.
|
61 |
+
* @param mixed $version The version of the plugin.
|
62 |
+
*/
|
63 |
+
public function __construct( $plugin = '', $version = 0 ) {
|
64 |
+
$this->plugin = $plugin;
|
65 |
+
$this->plugin_version = $version;
|
66 |
+
|
67 |
+
add_action( 'init', array( $this, 'custom_post_type' ) );
|
68 |
+
add_action( 'admin_init', array( $this, 'get_remote_notifications' ), 100 );
|
69 |
+
add_action( 'admin_notices', array( $this, 'display_notifications' ) );
|
70 |
+
add_action( 'wp_ajax_am_notification_dismiss', array( $this, 'dismiss_notification' ) );
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Registers a custom post type.
|
75 |
+
*
|
76 |
+
* @since 1.0.0
|
77 |
+
*/
|
78 |
+
public function custom_post_type() {
|
79 |
+
register_post_type( 'amn_' . $this->plugin, array(
|
80 |
+
'label' => $this->plugin . ' Announcements',
|
81 |
+
'can_export' => false,
|
82 |
+
'supports' => false,
|
83 |
+
) );
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Retrieve the remote notifications if the time has expired.
|
88 |
+
*
|
89 |
+
* @since 1.0.0
|
90 |
+
*/
|
91 |
+
public function get_remote_notifications() {
|
92 |
+
if ( ! current_user_can( apply_filters( 'am_notifications_display', 'manage_options' ) ) ) {
|
93 |
+
return;
|
94 |
+
}
|
95 |
+
|
96 |
+
$last_checked = get_option( '_amn_' . $this->plugin . '_last_checked', strtotime( '-1 week' ) );
|
97 |
+
|
98 |
+
if ( $last_checked < strtotime( 'today midnight' ) ) {
|
99 |
+
$plugin_notifications = $this->get_plugin_notifications( 1 );
|
100 |
+
$notification_id = null;
|
101 |
+
|
102 |
+
if ( ! empty( $plugin_notifications ) ) {
|
103 |
+
// Unset it from the array.
|
104 |
+
$notification = $plugin_notifications[0];
|
105 |
+
$notification_id = get_post_meta( $notification->ID, 'notification_id', true );
|
106 |
+
}
|
107 |
+
|
108 |
+
$response = wp_remote_retrieve_body( wp_remote_post( $this->api_url, array(
|
109 |
+
'body' => array(
|
110 |
+
'slug' => $this->plugin,
|
111 |
+
'version' => $this->plugin_version,
|
112 |
+
'last_notification' => $notification_id,
|
113 |
+
),
|
114 |
+
) ) );
|
115 |
+
|
116 |
+
$data = json_decode( $response );
|
117 |
+
|
118 |
+
if ( ! empty( $data->id ) ) {
|
119 |
+
$notifications = array();
|
120 |
+
|
121 |
+
foreach ( (array) $data->slugs as $slug ) {
|
122 |
+
$notifications = array_merge(
|
123 |
+
$notifications,
|
124 |
+
(array) get_posts(
|
125 |
+
array(
|
126 |
+
'post_type' => 'amn_' . $slug,
|
127 |
+
'post_status' => 'all',
|
128 |
+
'meta_key' => 'notification_id',
|
129 |
+
'meta_value' => $data->id,
|
130 |
+
)
|
131 |
+
)
|
132 |
+
);
|
133 |
+
}
|
134 |
+
|
135 |
+
if ( empty( $notifications ) ) {
|
136 |
+
$new_notification_id = wp_insert_post( array(
|
137 |
+
'post_content' => wp_kses_post( $data->content ),
|
138 |
+
'post_type' => 'amn_' . $this->plugin,
|
139 |
+
) );
|
140 |
+
|
141 |
+
update_post_meta( $new_notification_id, 'notification_id', absint( $data->id ) );
|
142 |
+
update_post_meta( $new_notification_id, 'type', sanitize_text_field( trim( $data->type ) ) );
|
143 |
+
update_post_meta( $new_notification_id, 'dismissable', (bool) $data->dismissible ? 1 : 0 );
|
144 |
+
update_post_meta( $new_notification_id, 'location', function_exists( 'wp_json_encode' ) ? wp_json_encode( $data->location ) : json_encode( $data->location ) );
|
145 |
+
update_post_meta( $new_notification_id, 'version', sanitize_text_field( trim( $data->version ) ) );
|
146 |
+
update_post_meta( $new_notification_id, 'viewed', 0 );
|
147 |
+
update_post_meta( $new_notification_id, 'expiration', $data->expiration ? absint( $data->expiration ) : false );
|
148 |
+
update_post_meta( $new_notification_id, 'plans', function_exists( 'wp_json_encode' ) ? wp_json_encode( $data->plans ) : json_encode( $data->plans ) );
|
149 |
+
}
|
150 |
+
}
|
151 |
+
|
152 |
+
// Possibly revoke notifications.
|
153 |
+
if ( ! empty( $data->revoked ) ) {
|
154 |
+
$this->revoke_notifications( $data->revoked );
|
155 |
+
}
|
156 |
+
|
157 |
+
// Set the option now so we can't run this again until after 24 hours.
|
158 |
+
update_option( '_amn_' . $this->plugin . '_last_checked', strtotime( 'today midnight' ) );
|
159 |
+
}
|
160 |
+
}
|
161 |
+
|
162 |
+
/**
|
163 |
+
* Get local plugin notifications that have already been set.
|
164 |
+
*
|
165 |
+
* @since 1.0.0
|
166 |
+
*
|
167 |
+
* @param integer $limit Set the limit for how many posts to retrieve.
|
168 |
+
* @param array $args Any top-level arguments to add to the array.
|
169 |
+
*
|
170 |
+
* @return WP_Post[] WP_Post that match the query.
|
171 |
+
*/
|
172 |
+
public function get_plugin_notifications( $limit = -1, $args = array() ) {
|
173 |
+
return get_posts(
|
174 |
+
array(
|
175 |
+
'posts_per_page' => $limit,
|
176 |
+
'post_type' => 'amn_' . $this->plugin,
|
177 |
+
) + $args
|
178 |
+
);
|
179 |
+
}
|
180 |
+
|
181 |
+
/**
|
182 |
+
* Display any notifications that should be displayed.
|
183 |
+
*
|
184 |
+
* @since 1.0.0
|
185 |
+
*/
|
186 |
+
public function display_notifications() {
|
187 |
+
if ( ! current_user_can( apply_filters( 'am_notifications_display', 'manage_options' ) ) ) {
|
188 |
+
return;
|
189 |
+
}
|
190 |
+
|
191 |
+
$plugin_notifications = $this->get_plugin_notifications( -1, array(
|
192 |
+
'post_status' => 'all',
|
193 |
+
'meta_key' => 'viewed',
|
194 |
+
'meta_value' => '0',
|
195 |
+
) );
|
196 |
+
|
197 |
+
$plugin_notifications = $this->validate_notifications( $plugin_notifications );
|
198 |
+
|
199 |
+
if ( ! empty( $plugin_notifications ) && ! self::$registered ) {
|
200 |
+
foreach ( $plugin_notifications as $notification ) {
|
201 |
+
$dismissable = get_post_meta( $notification->ID, 'dismissable', true );
|
202 |
+
$type = get_post_meta( $notification->ID, 'type', true );
|
203 |
+
?>
|
204 |
+
<div class="am-notification am-notification-<?php echo $notification->ID; ?> notice notice-<?php echo $type; ?><?php echo $dismissable ? ' is-dismissible' : ''; ?>">
|
205 |
+
<?php echo $notification->post_content; ?>
|
206 |
+
</div>
|
207 |
+
<script type="text/javascript">
|
208 |
+
jQuery(document).ready(function ($) {
|
209 |
+
$(document).on('click', '.am-notification-<?php echo $notification->ID; ?> button.notice-dismiss', function (event) {
|
210 |
+
$.post(ajaxurl, {
|
211 |
+
action: 'am_notification_dismiss',
|
212 |
+
notification_id: '<?php echo $notification->ID; ?>'
|
213 |
+
});
|
214 |
+
});
|
215 |
+
});
|
216 |
+
</script>
|
217 |
+
<?php
|
218 |
+
}
|
219 |
+
|
220 |
+
self::$registered = true;
|
221 |
+
}
|
222 |
+
}
|
223 |
+
|
224 |
+
/**
|
225 |
+
* Validate the notifications before displaying them.
|
226 |
+
*
|
227 |
+
* @since 1.0.0
|
228 |
+
*
|
229 |
+
* @param array $plugin_notifications An array of plugin notifications.
|
230 |
+
*
|
231 |
+
* @return array A filtered array of plugin notifications.
|
232 |
+
*/
|
233 |
+
public function validate_notifications( $plugin_notifications ) {
|
234 |
+
global $pagenow;
|
235 |
+
|
236 |
+
foreach ( $plugin_notifications as $key => $notification ) {
|
237 |
+
// Location validation.
|
238 |
+
$location = (array) json_decode( get_post_meta( $notification->ID, 'location', true ) );
|
239 |
+
$continue = false;
|
240 |
+
if ( ! in_array( 'everywhere', $location, true ) ) {
|
241 |
+
if ( in_array( 'index.php', $location, true ) && 'index.php' === $pagenow ) {
|
242 |
+
$continue = true;
|
243 |
+
}
|
244 |
+
|
245 |
+
if ( in_array( 'plugins.php', $location, true ) && 'plugins.php' === $pagenow ) {
|
246 |
+
$continue = true;
|
247 |
+
}
|
248 |
+
|
249 |
+
if ( ! $continue ) {
|
250 |
+
unset( $plugin_notifications[ $key ] );
|
251 |
+
}
|
252 |
+
}
|
253 |
+
|
254 |
+
// Plugin validation (OR conditional).
|
255 |
+
$plugins = (array) json_decode( get_post_meta( $notification->ID, 'plugins', true ) );
|
256 |
+
$continue = false;
|
257 |
+
if ( ! empty( $plugins ) ) {
|
258 |
+
foreach ( $plugins as $plugin ) {
|
259 |
+
if ( is_plugin_active( $plugin ) ) {
|
260 |
+
$continue = true;
|
261 |
+
}
|
262 |
+
}
|
263 |
+
|
264 |
+
if ( ! $continue ) {
|
265 |
+
unset( $plugin_notifications[ $key ] );
|
266 |
+
}
|
267 |
+
}
|
268 |
+
|
269 |
+
// Theme validation.
|
270 |
+
$theme = get_post_meta( $notification->ID, 'theme', true );
|
271 |
+
$continue = (string) wp_get_theme() === $theme;
|
272 |
+
|
273 |
+
if ( ! empty( $theme ) && ! $continue ) {
|
274 |
+
unset( $plugin_notifications[ $key ] );
|
275 |
+
}
|
276 |
+
|
277 |
+
// Version validation.
|
278 |
+
$version = get_post_meta( $notification->ID, 'version', true );
|
279 |
+
$continue = false;
|
280 |
+
if ( ! empty( $version ) ) {
|
281 |
+
if ( version_compare( $this->plugin_version, $version, '<=' ) ) {
|
282 |
+
$continue = true;
|
283 |
+
}
|
284 |
+
|
285 |
+
if ( ! $continue ) {
|
286 |
+
unset( $plugin_notifications[ $key ] );
|
287 |
+
}
|
288 |
+
}
|
289 |
+
|
290 |
+
// Expiration validation.
|
291 |
+
$expiration = get_post_meta( $notification->ID, 'expiration', true );
|
292 |
+
$continue = false;
|
293 |
+
if ( ! empty( $expiration ) ) {
|
294 |
+
if ( $expiration > time() ) {
|
295 |
+
$continue = true;
|
296 |
+
}
|
297 |
+
|
298 |
+
if ( ! $continue ) {
|
299 |
+
unset( $plugin_notifications[ $key ] );
|
300 |
+
}
|
301 |
+
}
|
302 |
+
|
303 |
+
// Plan validation.
|
304 |
+
$plans = (array) json_decode( get_post_meta( $notification->ID, 'plans', true ) );
|
305 |
+
$continue = false;
|
306 |
+
if ( ! empty( $plans ) ) {
|
307 |
+
$level = $this->get_plan_level();
|
308 |
+
if ( in_array( $level, $plans, true ) ) {
|
309 |
+
$continue = true;
|
310 |
+
}
|
311 |
+
|
312 |
+
if ( ! $continue ) {
|
313 |
+
unset( $plugin_notifications[ $key ] );
|
314 |
+
}
|
315 |
+
}
|
316 |
+
}
|
317 |
+
|
318 |
+
return $plugin_notifications;
|
319 |
+
}
|
320 |
+
|
321 |
+
/**
|
322 |
+
* Grab the current plan level.
|
323 |
+
*
|
324 |
+
* @since 1.0.0
|
325 |
+
*
|
326 |
+
* @return string The current plan level.
|
327 |
+
*/
|
328 |
+
public function get_plan_level() {
|
329 |
+
// Prepare variables.
|
330 |
+
$key = '';
|
331 |
+
$level = '';
|
332 |
+
$option = false;
|
333 |
+
switch ( $this->plugin ) {
|
334 |
+
case 'wpforms' :
|
335 |
+
$option = get_option( 'wpforms_license' );
|
336 |
+
$key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
|
337 |
+
$level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
|
338 |
+
|
339 |
+
// Possibly check for a constant.
|
340 |
+
if ( empty( $key ) && defined( 'WPFORMS_LICENSE_KEY' ) ) {
|
341 |
+
$key = WPFORMS_LICENSE_KEY;
|
342 |
+
}
|
343 |
+
break;
|
344 |
+
case 'mi' :
|
345 |
+
$option = get_option( 'monsterinsights_license' );
|
346 |
+
$key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
|
347 |
+
$level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
|
348 |
+
|
349 |
+
// Possibly check for a constant.
|
350 |
+
if ( empty( $key ) && defined( 'MONSTERINSIGHTS_LICENSE_KEY' ) && is_string( MONSTERINSIGHTS_LICENSE_KEY ) && strlen( MONSTERINSIGHTS_LICENSE_KEY ) > 10 ) {
|
351 |
+
$key = MONSTERINSIGHTS_LICENSE_KEY;
|
352 |
+
}
|
353 |
+
break;
|
354 |
+
case 'sol' :
|
355 |
+
$option = get_option( 'soliloquy' );
|
356 |
+
$key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
|
357 |
+
$level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
|
358 |
+
|
359 |
+
// Possibly check for a constant.
|
360 |
+
if ( empty( $key ) && defined( 'SOLILOQUY_LICENSE_KEY' ) ) {
|
361 |
+
$key = SOLILOQUY_LICENSE_KEY;
|
362 |
+
}
|
363 |
+
break;
|
364 |
+
case 'envira' :
|
365 |
+
$option = get_option( 'envira_gallery' );
|
366 |
+
$key = is_array( $option ) && isset( $option['key'] ) ? $option['key'] : '';
|
367 |
+
$level = is_array( $option ) && isset( $option['type'] ) ? $option['type'] : '';
|
368 |
+
|
369 |
+
// Possibly check for a constant.
|
370 |
+
if ( empty( $key ) && defined( 'ENVIRA_LICENSE_KEY' ) ) {
|
371 |
+
$key = ENVIRA_LICENSE_KEY;
|
372 |
+
}
|
373 |
+
break;
|
374 |
+
case 'om' :
|
375 |
+
$option = get_option( 'optin_monster_api' );
|
376 |
+
$key = is_array( $option ) && isset( $option['api']['apikey'] ) ? $option['api']['apikey'] : '';
|
377 |
+
|
378 |
+
// Possibly check for a constant.
|
379 |
+
if ( empty( $key ) && defined( 'OPTINMONSTER_REST_API_LICENSE_KEY' ) ) {
|
380 |
+
$key = OPTINMONSTER_REST_API_LICENSE_KEY;
|
381 |
+
}
|
382 |
+
|
383 |
+
// If the key is still empty, check for the old legacy key.
|
384 |
+
if ( empty( $key ) ) {
|
385 |
+
$key = is_array( $option ) && isset( $option['api']['key'] ) ? $option['api']['key'] : '';
|
386 |
+
}
|
387 |
+
break;
|
388 |
+
}
|
389 |
+
|
390 |
+
// Possibly set the level to 'none' if the key is empty and no level has been set.
|
391 |
+
if ( empty( $key ) && empty( $level ) ) {
|
392 |
+
$level = 'none';
|
393 |
+
}
|
394 |
+
|
395 |
+
// Normalize the level.
|
396 |
+
switch ( $level ) {
|
397 |
+
case 'bronze' :
|
398 |
+
case 'personal' :
|
399 |
+
$level = 'basic';
|
400 |
+
break;
|
401 |
+
case 'silver' :
|
402 |
+
case 'multi' :
|
403 |
+
$level = 'plus';
|
404 |
+
break;
|
405 |
+
case 'gold' :
|
406 |
+
case 'developer' :
|
407 |
+
$level = 'pro';
|
408 |
+
break;
|
409 |
+
case 'platinum' :
|
410 |
+
case 'master' :
|
411 |
+
$level = 'ultimate';
|
412 |
+
break;
|
413 |
+
}
|
414 |
+
|
415 |
+
// Return the plan level.
|
416 |
+
return $level;
|
417 |
+
}
|
418 |
+
|
419 |
+
/**
|
420 |
+
* Dismiss the notification via AJAX.
|
421 |
+
*
|
422 |
+
* @since 1.0.0
|
423 |
+
*/
|
424 |
+
public function dismiss_notification() {
|
425 |
+
if ( ! current_user_can( apply_filters( 'am_notifications_display', 'manage_options' ) ) ) {
|
426 |
+
die;
|
427 |
+
}
|
428 |
+
|
429 |
+
$notification_id = intval( $_POST['notification_id'] );
|
430 |
+
update_post_meta( $notification_id, 'viewed', 1 );
|
431 |
+
die;
|
432 |
+
}
|
433 |
+
|
434 |
+
/**
|
435 |
+
* Revokes notifications.
|
436 |
+
*
|
437 |
+
* @since 1.0.0
|
438 |
+
*
|
439 |
+
* @param array $ids An array of notification IDs to revoke.
|
440 |
+
*/
|
441 |
+
public function revoke_notifications( $ids ) {
|
442 |
+
// Loop through each of the IDs and find the post that has it as meta.
|
443 |
+
foreach ( (array) $ids as $id ) {
|
444 |
+
$notifications = $this->get_plugin_notifications( -1, array( 'post_status' => 'all', 'meta_key' => 'notification_id', 'meta_value' => $id ) );
|
445 |
+
if ( $notifications ) {
|
446 |
+
foreach ( $notifications as $notification ) {
|
447 |
+
update_post_meta( $notification->ID, 'viewed', 1 );
|
448 |
+
}
|
449 |
+
}
|
450 |
+
}
|
451 |
+
}
|
452 |
+
}
|
src/Admin/Area.php
CHANGED
@@ -1,457 +1,457 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Admin;
|
4 |
-
|
5 |
-
use WPMailSMTP\WP;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Class Area registers and process all wp-admin display functionality.
|
9 |
-
*
|
10 |
-
* @since 1.0.0
|
11 |
-
*/
|
12 |
-
class Area {
|
13 |
-
|
14 |
-
/**
|
15 |
-
* @var string Slug of the admin area page.
|
16 |
-
*/
|
17 |
-
const SLUG = 'wp-mail-smtp';
|
18 |
-
|
19 |
-
/**
|
20 |
-
* @var string Admin page unique hook.
|
21 |
-
*/
|
22 |
-
public $hook;
|
23 |
-
|
24 |
-
/**
|
25 |
-
* @var PageAbstract[]
|
26 |
-
*/
|
27 |
-
private $pages;
|
28 |
-
|
29 |
-
/**
|
30 |
-
* Area constructor.
|
31 |
-
*
|
32 |
-
* @since 1.0.0
|
33 |
-
*/
|
34 |
-
public function __construct() {
|
35 |
-
$this->hooks();
|
36 |
-
}
|
37 |
-
|
38 |
-
/**
|
39 |
-
* Assign all hooks to proper places.
|
40 |
-
*
|
41 |
-
* @since 1.0.0
|
42 |
-
*/
|
43 |
-
protected function hooks() {
|
44 |
-
|
45 |
-
// Add the Settings link to a plugin on Plugins page.
|
46 |
-
add_filter( 'plugin_action_links', array( $this, 'add_plugin_action_link' ), 10, 2 );
|
47 |
-
|
48 |
-
// Add the options page.
|
49 |
-
add_action( 'admin_menu', array( $this, 'add_admin_options_page' ) );
|
50 |
-
|
51 |
-
// Admin footer text.
|
52 |
-
add_filter( 'admin_footer_text', array( $this, 'get_admin_footer' ), 1, 2 );
|
53 |
-
|
54 |
-
// Enqueue admin area scripts and styles.
|
55 |
-
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
|
56 |
-
|
57 |
-
// Process the admin page forms actions.
|
58 |
-
add_action( 'admin_init', array( $this, 'process_actions' ) );
|
59 |
-
|
60 |
-
// Display custom notices based on the error/success codes.
|
61 |
-
add_action( 'admin_init', array( $this, 'display_custom_auth_notices' ) );
|
62 |
-
|
63 |
-
// Outputs the plugin admin header.
|
64 |
-
add_action( 'in_admin_header', array( $this, 'display_admin_header' ), 100 );
|
65 |
-
|
66 |
-
// Hide all unrelated to the plugin notices on the plugin admin pages.
|
67 |
-
add_action( 'admin_print_scripts', array( $this, 'hide_unrelated_notices' ) );
|
68 |
-
}
|
69 |
-
|
70 |
-
/**
|
71 |
-
* Display custom notices based on the error/success codes.
|
72 |
-
*
|
73 |
-
* @since 1.0.0
|
74 |
-
*/
|
75 |
-
public function display_custom_auth_notices() {
|
76 |
-
|
77 |
-
$error = isset( $_GET['error'] ) ? $_GET['error'] : '';
|
78 |
-
$success = isset( $_GET['success'] ) ? $_GET['success'] : '';
|
79 |
-
|
80 |
-
if ( empty( $error ) && empty( $success ) ) {
|
81 |
-
return;
|
82 |
-
}
|
83 |
-
|
84 |
-
switch ( $error ) {
|
85 |
-
case 'google_access_denied':
|
86 |
-
WP::add_admin_notice(
|
87 |
-
/* translators: %s - error code, returned by Google API. */
|
88 |
-
sprintf( esc_html__( 'There was an error while processing the authentication request: %s. Please try again.', 'wp-mail-smtp' ), '<code>' . $error . '</code>' ),
|
89 |
-
WP::ADMIN_NOTICE_ERROR
|
90 |
-
);
|
91 |
-
break;
|
92 |
-
|
93 |
-
case 'google_no_code_scope':
|
94 |
-
WP::add_admin_notice(
|
95 |
-
esc_html__( 'There was an error while processing the authentication request. Please try again.', 'wp-mail-smtp' ),
|
96 |
-
WP::ADMIN_NOTICE_ERROR
|
97 |
-
);
|
98 |
-
break;
|
99 |
-
|
100 |
-
case 'google_no_clients':
|
101 |
-
WP::add_admin_notice(
|
102 |
-
esc_html__( 'There was an error while processing the authentication request. Please make sure that you have Client ID and Client Secret both valid and saved.', 'wp-mail-smtp' ),
|
103 |
-
WP::ADMIN_NOTICE_ERROR
|
104 |
-
);
|
105 |
-
break;
|
106 |
-
}
|
107 |
-
|
108 |
-
switch ( $success ) {
|
109 |
-
case 'google_site_linked':
|
110 |
-
WP::add_admin_notice(
|
111 |
-
esc_html__( 'You have successfully linked the current site with you Google API project. Now you can start sending emails through Google.', 'wp-mail-smtp' ),
|
112 |
-
WP::ADMIN_NOTICE_SUCCESS
|
113 |
-
);
|
114 |
-
break;
|
115 |
-
}
|
116 |
-
}
|
117 |
-
|
118 |
-
/**
|
119 |
-
* Add admin area menu item.
|
120 |
-
*
|
121 |
-
* @since 1.0.0
|
122 |
-
*/
|
123 |
-
public function add_admin_options_page() {
|
124 |
-
|
125 |
-
$this->hook = add_options_page(
|
126 |
-
esc_html__( 'WP Mail SMTP Options', 'wp-mail-smtp' ),
|
127 |
-
esc_html__( 'WP Mail SMTP', 'wp-mail-smtp' ),
|
128 |
-
'manage_options',
|
129 |
-
self::SLUG,
|
130 |
-
array( $this, 'display' )
|
131 |
-
);
|
132 |
-
}
|
133 |
-
|
134 |
-
/**
|
135 |
-
* Enqueue admin area scripts and styles.
|
136 |
-
*
|
137 |
-
* @since 1.0.0
|
138 |
-
*
|
139 |
-
* @param string $hook
|
140 |
-
*/
|
141 |
-
public function enqueue_assets( $hook ) {
|
142 |
-
|
143 |
-
if ( $hook !== $this->hook ) {
|
144 |
-
return;
|
145 |
-
}
|
146 |
-
|
147 |
-
wp_enqueue_style(
|
148 |
-
'wp-mail-smtp-admin',
|
149 |
-
wp_mail_smtp()->plugin_url . '/assets/css/smtp-admin.min.css',
|
150 |
-
false,
|
151 |
-
WPMS_PLUGIN_VER
|
152 |
-
);
|
153 |
-
|
154 |
-
wp_enqueue_script(
|
155 |
-
'wp-mail-smtp-admin',
|
156 |
-
wp_mail_smtp()->plugin_url . '/assets/js/smtp-admin' . WP::asset_min() . '.js',
|
157 |
-
array( 'jquery' ),
|
158 |
-
WPMS_PLUGIN_VER
|
159 |
-
);
|
160 |
-
}
|
161 |
-
|
162 |
-
/**
|
163 |
-
* Outputs the plugin admin header.
|
164 |
-
*
|
165 |
-
* @since 1.0.0
|
166 |
-
*/
|
167 |
-
public function display_admin_header() {
|
168 |
-
|
169 |
-
// Bail if we're not on a plugin page.
|
170 |
-
if ( ! $this->is_admin_page() ) {
|
171 |
-
return;
|
172 |
-
}
|
173 |
-
?>
|
174 |
-
|
175 |
-
<div id="wp-mail-smtp-header">
|
176 |
-
<!--suppress HtmlUnknownTarget -->
|
177 |
-
<img class="wp-mail-smtp-header-logo" src="<?php echo wp_mail_smtp()->plugin_url; ?>/assets/images/logo.png" alt="WP Mail SMTP"/>
|
178 |
-
</div>
|
179 |
-
|
180 |
-
<?php
|
181 |
-
}
|
182 |
-
|
183 |
-
/**
|
184 |
-
* Display a text to ask users to review the plugin on WP.org.
|
185 |
-
*
|
186 |
-
* @since 1.0.0
|
187 |
-
*
|
188 |
-
* @param string $text
|
189 |
-
*
|
190 |
-
* @return string
|
191 |
-
*/
|
192 |
-
public function get_admin_footer( $text ) {
|
193 |
-
|
194 |
-
if ( $this->is_admin_page() ) {
|
195 |
-
$url = 'https://wordpress.org/support/plugin/wp-mail-smtp/reviews/?filter=5#new-post';
|
196 |
-
|
197 |
-
$text = sprintf(
|
198 |
-
/* translators: %1$s - WP.org link; %2$s - same WP.org link. */
|
199 |
-
__( 'Please rate <strong>WP Mail SMTP</strong> <a href="%1$s" target="_blank" rel="noopener noreferrer">★★★★★</a> on <a href="%2$s" target="_blank">WordPress.org</a> to help us spread the word. Thank you from the WP Mail SMTP team!', 'wp-mail-smtp' ),
|
200 |
-
$url,
|
201 |
-
$url
|
202 |
-
);
|
203 |
-
}
|
204 |
-
|
205 |
-
return $text;
|
206 |
-
}
|
207 |
-
|
208 |
-
/**
|
209 |
-
* Display content of the admin area page.
|
210 |
-
*
|
211 |
-
* @since 1.0.0
|
212 |
-
*/
|
213 |
-
public function display() {
|
214 |
-
?>
|
215 |
-
|
216 |
-
<div class="wrap" id="wp-mail-smtp">
|
217 |
-
|
218 |
-
<div class="wp-mail-smtp-page-title">
|
219 |
-
<?php
|
220 |
-
foreach ( $this->get_pages() as $page_slug => $page ) :
|
221 |
-
$label = $page->get_label();
|
222 |
-
if ( empty( $label ) ) {
|
223 |
-
continue;
|
224 |
-
}
|
225 |
-
$class = $page_slug === $this->get_current_tab() ? 'class="active"' : '';
|
226 |
-
?>
|
227 |
-
|
228 |
-
<a href="<?php echo $page->get_link(); ?>" <?php echo $class; ?>><?php echo $label; ?></a>
|
229 |
-
|
230 |
-
<?php endforeach; ?>
|
231 |
-
</div>
|
232 |
-
|
233 |
-
<div class="wp-mail-smtp-page wp-mail-smtp-tab-<?php echo $this->get_current_tab(); ?>">
|
234 |
-
<h1 class="screen-reader-text"><?php echo $this->get_current_tab_title(); ?></h1>
|
235 |
-
|
236 |
-
<?php $this->display_current_tab_content(); ?>
|
237 |
-
</div>
|
238 |
-
|
239 |
-
</div>
|
240 |
-
|
241 |
-
<?php
|
242 |
-
}
|
243 |
-
|
244 |
-
/**
|
245 |
-
* Get the current tab title.
|
246 |
-
*
|
247 |
-
* @since 1.0.0
|
248 |
-
*/
|
249 |
-
public function display_current_tab_content() {
|
250 |
-
|
251 |
-
if ( ! array_key_exists( $this->get_current_tab(), $this->get_pages() ) ) {
|
252 |
-
return;
|
253 |
-
}
|
254 |
-
|
255 |
-
$this->pages[ $this->get_current_tab() ]->display();
|
256 |
-
}
|
257 |
-
|
258 |
-
/**
|
259 |
-
* Get the current admin area tab.
|
260 |
-
*
|
261 |
-
* @since 1.0.0
|
262 |
-
*
|
263 |
-
* @return string
|
264 |
-
*/
|
265 |
-
protected function get_current_tab() {
|
266 |
-
|
267 |
-
$current = '';
|
268 |
-
|
269 |
-
if ( $this->is_admin_page() ) {
|
270 |
-
$current = ! empty( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : 'settings';
|
271 |
-
}
|
272 |
-
|
273 |
-
return $current;
|
274 |
-
}
|
275 |
-
|
276 |
-
/**
|
277 |
-
* Get the array of default registered tabs for plugin admin area.
|
278 |
-
*
|
279 |
-
* @since 1.0.0
|
280 |
-
*
|
281 |
-
* @return \WPMailSMTP\Admin\PageAbstract[]
|
282 |
-
*/
|
283 |
-
public function get_pages() {
|
284 |
-
|
285 |
-
if ( empty( $this->pages ) ) {
|
286 |
-
$this->pages = array(
|
287 |
-
'settings' => new Pages\Settings(),
|
288 |
-
'test' => new Pages\Test(),
|
289 |
-
'misc' => new Pages\Misc(),
|
290 |
-
'auth' => new Pages\Auth(),
|
291 |
-
);
|
292 |
-
}
|
293 |
-
|
294 |
-
return apply_filters( 'wp_mail_smtp_admin_get_pages', $this->pages );
|
295 |
-
}
|
296 |
-
|
297 |
-
/**
|
298 |
-
* Get the current tab title.
|
299 |
-
*
|
300 |
-
* @since 1.0.0
|
301 |
-
*
|
302 |
-
* @return string
|
303 |
-
*/
|
304 |
-
public function get_current_tab_title() {
|
305 |
-
|
306 |
-
if ( ! array_key_exists( $this->get_current_tab(), $this->get_pages() ) ) {
|
307 |
-
return '';
|
308 |
-
}
|
309 |
-
|
310 |
-
return $this->pages[ $this->get_current_tab() ]->get_title();
|
311 |
-
}
|
312 |
-
|
313 |
-
/**
|
314 |
-
* Check whether we are on an admin page.
|
315 |
-
*
|
316 |
-
* @since 1.0.0
|
317 |
-
*
|
318 |
-
* @return bool
|
319 |
-
*/
|
320 |
-
public function is_admin_page() {
|
321 |
-
|
322 |
-
$page = isset( $_GET['page'] ) ? $_GET['page'] : '';
|
323 |
-
|
324 |
-
return self::SLUG === $page;
|
325 |
-
}
|
326 |
-
|
327 |
-
/**
|
328 |
-
* All possible plugin forms manipulation will be done here.
|
329 |
-
*
|
330 |
-
* @since 1.0.0
|
331 |
-
*/
|
332 |
-
public function process_actions() {
|
333 |
-
|
334 |
-
// Allow to process only own tabs.
|
335 |
-
if ( ! array_key_exists( $this->get_current_tab(), $this->get_pages() ) ) {
|
336 |
-
return;
|
337 |
-
}
|
338 |
-
|
339 |
-
// Process POST only if it exists.
|
340 |
-
if ( ! empty( $_POST ) ) {
|
341 |
-
if ( ! empty( $_POST['wp-mail-smtp'] ) ) {
|
342 |
-
$post = $_POST['wp-mail-smtp'];
|
343 |
-
} else {
|
344 |
-
$post = array();
|
345 |
-
}
|
346 |
-
|
347 |
-
$this->pages[ $this->get_current_tab() ]->process_post( $post );
|
348 |
-
}
|
349 |
-
|
350 |
-
// This won't do anything for most pages.
|
351 |
-
$this->pages[ $this->get_current_tab() ]->process_auth();
|
352 |
-
}
|
353 |
-
|
354 |
-
/**
|
355 |
-
* Add a link to Settings page of a plugin on Plugins page.
|
356 |
-
*
|
357 |
-
* @since 1.0.0
|
358 |
-
*
|
359 |
-
* @param array $links
|
360 |
-
* @param string $file
|
361 |
-
*
|
362 |
-
* @return mixed
|
363 |
-
*/
|
364 |
-
public function add_plugin_action_link( $links, $file ) {
|
365 |
-
|
366 |
-
if ( strpos( $file, 'wp-mail-smtp' ) === false ) {
|
367 |
-
return $links;
|
368 |
-
}
|
369 |
-
|
370 |
-
$settings_link = '<a href="' . $this->get_admin_page_url() . '">' . esc_html__( 'Settings', 'wp-mail-smtp' ) . '</a>';
|
371 |
-
|
372 |
-
array_unshift( $links, $settings_link );
|
373 |
-
|
374 |
-
return $links;
|
375 |
-
}
|
376 |
-
|
377 |
-
/**
|
378 |
-
* Get plugin admin area page URL.
|
379 |
-
*
|
380 |
-
* @since 1.0.0
|
381 |
-
*
|
382 |
-
* @return string
|
383 |
-
*/
|
384 |
-
public function get_admin_page_url() {
|
385 |
-
return add_query_arg(
|
386 |
-
'page',
|
387 |
-
self::SLUG,
|
388 |
-
admin_url( 'options-general.php' )
|
389 |
-
);
|
390 |
-
}
|
391 |
-
|
392 |
-
/**
|
393 |
-
* Remove all non-WP Mail SMTP plugin notices from plugin pages.
|
394 |
-
*
|
395 |
-
* @since 1.0.0
|
396 |
-
*/
|
397 |
-
public function hide_unrelated_notices() {
|
398 |
-
|
399 |
-
// Bail if we're not on a our screen or page.
|
400 |
-
if ( empty( $_REQUEST['page'] ) || strpos( $_REQUEST['page'], self::SLUG ) === false ) {
|
401 |
-
return;
|
402 |
-
}
|
403 |
-
|
404 |
-
global $wp_filter;
|
405 |
-
|
406 |
-
if ( ! empty( $wp_filter['user_admin_notices']->callbacks ) && is_array( $wp_filter['user_admin_notices']->callbacks ) ) {
|
407 |
-
foreach ( $wp_filter['user_admin_notices']->callbacks as $priority => $hooks ) {
|
408 |
-
foreach ( $hooks as $name => $arr ) {
|
409 |
-
if ( is_object( $arr['function'] ) && $arr['function'] instanceof \Closure ) {
|
410 |
-
unset( $wp_filter['user_admin_notices']->callbacks[ $priority ][ $name ] );
|
411 |
-
continue;
|
412 |
-
}
|
413 |
-
if ( ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) && strpos( strtolower( get_class( $arr['function'][0] ) ), 'wpmailsmtp' ) !== false ) {
|
414 |
-
continue;
|
415 |
-
}
|
416 |
-
if ( ! empty( $name ) && strpos( strtolower( $name ), 'wpmailsmtp' ) === false ) {
|
417 |
-
unset( $wp_filter['user_admin_notices']->callbacks[ $priority ][ $name ] );
|
418 |
-
}
|
419 |
-
}
|
420 |
-
}
|
421 |
-
}
|
422 |
-
|
423 |
-
if ( ! empty( $wp_filter['admin_notices']->callbacks ) && is_array( $wp_filter['admin_notices']->callbacks ) ) {
|
424 |
-
foreach ( $wp_filter['admin_notices']->callbacks as $priority => $hooks ) {
|
425 |
-
foreach ( $hooks as $name => $arr ) {
|
426 |
-
if ( is_object( $arr['function'] ) && $arr['function'] instanceof \Closure ) {
|
427 |
-
unset( $wp_filter['admin_notices']->callbacks[ $priority ][ $name ] );
|
428 |
-
continue;
|
429 |
-
}
|
430 |
-
if ( ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) && strpos( strtolower( get_class( $arr['function'][0] ) ), 'wpmailsmtp' ) !== false ) {
|
431 |
-
continue;
|
432 |
-
}
|
433 |
-
if ( ! empty( $name ) && strpos( strtolower( $name ), 'wpmailsmtp' ) === false ) {
|
434 |
-
unset( $wp_filter['admin_notices']->callbacks[ $priority ][ $name ] );
|
435 |
-
}
|
436 |
-
}
|
437 |
-
}
|
438 |
-
}
|
439 |
-
|
440 |
-
if ( ! empty( $wp_filter['all_admin_notices']->callbacks ) && is_array( $wp_filter['all_admin_notices']->callbacks ) ) {
|
441 |
-
foreach ( $wp_filter['all_admin_notices']->callbacks as $priority => $hooks ) {
|
442 |
-
foreach ( $hooks as $name => $arr ) {
|
443 |
-
if ( is_object( $arr['function'] ) && $arr['function'] instanceof \Closure ) {
|
444 |
-
unset( $wp_filter['all_admin_notices']->callbacks[ $priority ][ $name ] );
|
445 |
-
continue;
|
446 |
-
}
|
447 |
-
if ( ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) && strpos( strtolower( get_class( $arr['function'][0] ) ), 'wpmailsmtp' ) !== false ) {
|
448 |
-
continue;
|
449 |
-
}
|
450 |
-
if ( ! empty( $name ) && strpos( strtolower( $name ), 'wpmailsmtp' ) === false ) {
|
451 |
-
unset( $wp_filter['all_admin_notices']->callbacks[ $priority ][ $name ] );
|
452 |
-
}
|
453 |
-
}
|
454 |
-
}
|
455 |
-
}
|
456 |
-
}
|
457 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Admin;
|
4 |
+
|
5 |
+
use WPMailSMTP\WP;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class Area registers and process all wp-admin display functionality.
|
9 |
+
*
|
10 |
+
* @since 1.0.0
|
11 |
+
*/
|
12 |
+
class Area {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var string Slug of the admin area page.
|
16 |
+
*/
|
17 |
+
const SLUG = 'wp-mail-smtp';
|
18 |
+
|
19 |
+
/**
|
20 |
+
* @var string Admin page unique hook.
|
21 |
+
*/
|
22 |
+
public $hook;
|
23 |
+
|
24 |
+
/**
|
25 |
+
* @var PageAbstract[]
|
26 |
+
*/
|
27 |
+
private $pages;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Area constructor.
|
31 |
+
*
|
32 |
+
* @since 1.0.0
|
33 |
+
*/
|
34 |
+
public function __construct() {
|
35 |
+
$this->hooks();
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Assign all hooks to proper places.
|
40 |
+
*
|
41 |
+
* @since 1.0.0
|
42 |
+
*/
|
43 |
+
protected function hooks() {
|
44 |
+
|
45 |
+
// Add the Settings link to a plugin on Plugins page.
|
46 |
+
add_filter( 'plugin_action_links', array( $this, 'add_plugin_action_link' ), 10, 2 );
|
47 |
+
|
48 |
+
// Add the options page.
|
49 |
+
add_action( 'admin_menu', array( $this, 'add_admin_options_page' ) );
|
50 |
+
|
51 |
+
// Admin footer text.
|
52 |
+
add_filter( 'admin_footer_text', array( $this, 'get_admin_footer' ), 1, 2 );
|
53 |
+
|
54 |
+
// Enqueue admin area scripts and styles.
|
55 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
|
56 |
+
|
57 |
+
// Process the admin page forms actions.
|
58 |
+
add_action( 'admin_init', array( $this, 'process_actions' ) );
|
59 |
+
|
60 |
+
// Display custom notices based on the error/success codes.
|
61 |
+
add_action( 'admin_init', array( $this, 'display_custom_auth_notices' ) );
|
62 |
+
|
63 |
+
// Outputs the plugin admin header.
|
64 |
+
add_action( 'in_admin_header', array( $this, 'display_admin_header' ), 100 );
|
65 |
+
|
66 |
+
// Hide all unrelated to the plugin notices on the plugin admin pages.
|
67 |
+
add_action( 'admin_print_scripts', array( $this, 'hide_unrelated_notices' ) );
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Display custom notices based on the error/success codes.
|
72 |
+
*
|
73 |
+
* @since 1.0.0
|
74 |
+
*/
|
75 |
+
public function display_custom_auth_notices() {
|
76 |
+
|
77 |
+
$error = isset( $_GET['error'] ) ? $_GET['error'] : '';
|
78 |
+
$success = isset( $_GET['success'] ) ? $_GET['success'] : '';
|
79 |
+
|
80 |
+
if ( empty( $error ) && empty( $success ) ) {
|
81 |
+
return;
|
82 |
+
}
|
83 |
+
|
84 |
+
switch ( $error ) {
|
85 |
+
case 'google_access_denied':
|
86 |
+
WP::add_admin_notice(
|
87 |
+
/* translators: %s - error code, returned by Google API. */
|
88 |
+
sprintf( esc_html__( 'There was an error while processing the authentication request: %s. Please try again.', 'wp-mail-smtp' ), '<code>' . $error . '</code>' ),
|
89 |
+
WP::ADMIN_NOTICE_ERROR
|
90 |
+
);
|
91 |
+
break;
|
92 |
+
|
93 |
+
case 'google_no_code_scope':
|
94 |
+
WP::add_admin_notice(
|
95 |
+
esc_html__( 'There was an error while processing the authentication request. Please try again.', 'wp-mail-smtp' ),
|
96 |
+
WP::ADMIN_NOTICE_ERROR
|
97 |
+
);
|
98 |
+
break;
|
99 |
+
|
100 |
+
case 'google_no_clients':
|
101 |
+
WP::add_admin_notice(
|
102 |
+
esc_html__( 'There was an error while processing the authentication request. Please make sure that you have Client ID and Client Secret both valid and saved.', 'wp-mail-smtp' ),
|
103 |
+
WP::ADMIN_NOTICE_ERROR
|
104 |
+
);
|
105 |
+
break;
|
106 |
+
}
|
107 |
+
|
108 |
+
switch ( $success ) {
|
109 |
+
case 'google_site_linked':
|
110 |
+
WP::add_admin_notice(
|
111 |
+
esc_html__( 'You have successfully linked the current site with you Google API project. Now you can start sending emails through Google.', 'wp-mail-smtp' ),
|
112 |
+
WP::ADMIN_NOTICE_SUCCESS
|
113 |
+
);
|
114 |
+
break;
|
115 |
+
}
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Add admin area menu item.
|
120 |
+
*
|
121 |
+
* @since 1.0.0
|
122 |
+
*/
|
123 |
+
public function add_admin_options_page() {
|
124 |
+
|
125 |
+
$this->hook = add_options_page(
|
126 |
+
esc_html__( 'WP Mail SMTP Options', 'wp-mail-smtp' ),
|
127 |
+
esc_html__( 'WP Mail SMTP', 'wp-mail-smtp' ),
|
128 |
+
'manage_options',
|
129 |
+
self::SLUG,
|
130 |
+
array( $this, 'display' )
|
131 |
+
);
|
132 |
+
}
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Enqueue admin area scripts and styles.
|
136 |
+
*
|
137 |
+
* @since 1.0.0
|
138 |
+
*
|
139 |
+
* @param string $hook
|
140 |
+
*/
|
141 |
+
public function enqueue_assets( $hook ) {
|
142 |
+
|
143 |
+
if ( $hook !== $this->hook ) {
|
144 |
+
return;
|
145 |
+
}
|
146 |
+
|
147 |
+
wp_enqueue_style(
|
148 |
+
'wp-mail-smtp-admin',
|
149 |
+
wp_mail_smtp()->plugin_url . '/assets/css/smtp-admin.min.css',
|
150 |
+
false,
|
151 |
+
WPMS_PLUGIN_VER
|
152 |
+
);
|
153 |
+
|
154 |
+
wp_enqueue_script(
|
155 |
+
'wp-mail-smtp-admin',
|
156 |
+
wp_mail_smtp()->plugin_url . '/assets/js/smtp-admin' . WP::asset_min() . '.js',
|
157 |
+
array( 'jquery' ),
|
158 |
+
WPMS_PLUGIN_VER
|
159 |
+
);
|
160 |
+
}
|
161 |
+
|
162 |
+
/**
|
163 |
+
* Outputs the plugin admin header.
|
164 |
+
*
|
165 |
+
* @since 1.0.0
|
166 |
+
*/
|
167 |
+
public function display_admin_header() {
|
168 |
+
|
169 |
+
// Bail if we're not on a plugin page.
|
170 |
+
if ( ! $this->is_admin_page() ) {
|
171 |
+
return;
|
172 |
+
}
|
173 |
+
?>
|
174 |
+
|
175 |
+
<div id="wp-mail-smtp-header">
|
176 |
+
<!--suppress HtmlUnknownTarget -->
|
177 |
+
<img class="wp-mail-smtp-header-logo" src="<?php echo wp_mail_smtp()->plugin_url; ?>/assets/images/logo.png" alt="WP Mail SMTP"/>
|
178 |
+
</div>
|
179 |
+
|
180 |
+
<?php
|
181 |
+
}
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Display a text to ask users to review the plugin on WP.org.
|
185 |
+
*
|
186 |
+
* @since 1.0.0
|
187 |
+
*
|
188 |
+
* @param string $text
|
189 |
+
*
|
190 |
+
* @return string
|
191 |
+
*/
|
192 |
+
public function get_admin_footer( $text ) {
|
193 |
+
|
194 |
+
if ( $this->is_admin_page() ) {
|
195 |
+
$url = 'https://wordpress.org/support/plugin/wp-mail-smtp/reviews/?filter=5#new-post';
|
196 |
+
|
197 |
+
$text = sprintf(
|
198 |
+
/* translators: %1$s - WP.org link; %2$s - same WP.org link. */
|
199 |
+
__( 'Please rate <strong>WP Mail SMTP</strong> <a href="%1$s" target="_blank" rel="noopener noreferrer">★★★★★</a> on <a href="%2$s" target="_blank">WordPress.org</a> to help us spread the word. Thank you from the WP Mail SMTP team!', 'wp-mail-smtp' ),
|
200 |
+
$url,
|
201 |
+
$url
|
202 |
+
);
|
203 |
+
}
|
204 |
+
|
205 |
+
return $text;
|
206 |
+
}
|
207 |
+
|
208 |
+
/**
|
209 |
+
* Display content of the admin area page.
|
210 |
+
*
|
211 |
+
* @since 1.0.0
|
212 |
+
*/
|
213 |
+
public function display() {
|
214 |
+
?>
|
215 |
+
|
216 |
+
<div class="wrap" id="wp-mail-smtp">
|
217 |
+
|
218 |
+
<div class="wp-mail-smtp-page-title">
|
219 |
+
<?php
|
220 |
+
foreach ( $this->get_pages() as $page_slug => $page ) :
|
221 |
+
$label = $page->get_label();
|
222 |
+
if ( empty( $label ) ) {
|
223 |
+
continue;
|
224 |
+
}
|
225 |
+
$class = $page_slug === $this->get_current_tab() ? 'class="active"' : '';
|
226 |
+
?>
|
227 |
+
|
228 |
+
<a href="<?php echo $page->get_link(); ?>" <?php echo $class; ?>><?php echo $label; ?></a>
|
229 |
+
|
230 |
+
<?php endforeach; ?>
|
231 |
+
</div>
|
232 |
+
|
233 |
+
<div class="wp-mail-smtp-page wp-mail-smtp-tab-<?php echo $this->get_current_tab(); ?>">
|
234 |
+
<h1 class="screen-reader-text"><?php echo $this->get_current_tab_title(); ?></h1>
|
235 |
+
|
236 |
+
<?php $this->display_current_tab_content(); ?>
|
237 |
+
</div>
|
238 |
+
|
239 |
+
</div>
|
240 |
+
|
241 |
+
<?php
|
242 |
+
}
|
243 |
+
|
244 |
+
/**
|
245 |
+
* Get the current tab title.
|
246 |
+
*
|
247 |
+
* @since 1.0.0
|
248 |
+
*/
|
249 |
+
public function display_current_tab_content() {
|
250 |
+
|
251 |
+
if ( ! array_key_exists( $this->get_current_tab(), $this->get_pages() ) ) {
|
252 |
+
return;
|
253 |
+
}
|
254 |
+
|
255 |
+
$this->pages[ $this->get_current_tab() ]->display();
|
256 |
+
}
|
257 |
+
|
258 |
+
/**
|
259 |
+
* Get the current admin area tab.
|
260 |
+
*
|
261 |
+
* @since 1.0.0
|
262 |
+
*
|
263 |
+
* @return string
|
264 |
+
*/
|
265 |
+
protected function get_current_tab() {
|
266 |
+
|
267 |
+
$current = '';
|
268 |
+
|
269 |
+
if ( $this->is_admin_page() ) {
|
270 |
+
$current = ! empty( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : 'settings';
|
271 |
+
}
|
272 |
+
|
273 |
+
return $current;
|
274 |
+
}
|
275 |
+
|
276 |
+
/**
|
277 |
+
* Get the array of default registered tabs for plugin admin area.
|
278 |
+
*
|
279 |
+
* @since 1.0.0
|
280 |
+
*
|
281 |
+
* @return \WPMailSMTP\Admin\PageAbstract[]
|
282 |
+
*/
|
283 |
+
public function get_pages() {
|
284 |
+
|
285 |
+
if ( empty( $this->pages ) ) {
|
286 |
+
$this->pages = array(
|
287 |
+
'settings' => new Pages\Settings(),
|
288 |
+
'test' => new Pages\Test(),
|
289 |
+
'misc' => new Pages\Misc(),
|
290 |
+
'auth' => new Pages\Auth(),
|
291 |
+
);
|
292 |
+
}
|
293 |
+
|
294 |
+
return apply_filters( 'wp_mail_smtp_admin_get_pages', $this->pages );
|
295 |
+
}
|
296 |
+
|
297 |
+
/**
|
298 |
+
* Get the current tab title.
|
299 |
+
*
|
300 |
+
* @since 1.0.0
|
301 |
+
*
|
302 |
+
* @return string
|
303 |
+
*/
|
304 |
+
public function get_current_tab_title() {
|
305 |
+
|
306 |
+
if ( ! array_key_exists( $this->get_current_tab(), $this->get_pages() ) ) {
|
307 |
+
return '';
|
308 |
+
}
|
309 |
+
|
310 |
+
return $this->pages[ $this->get_current_tab() ]->get_title();
|
311 |
+
}
|
312 |
+
|
313 |
+
/**
|
314 |
+
* Check whether we are on an admin page.
|
315 |
+
*
|
316 |
+
* @since 1.0.0
|
317 |
+
*
|
318 |
+
* @return bool
|
319 |
+
*/
|
320 |
+
public function is_admin_page() {
|
321 |
+
|
322 |
+
$page = isset( $_GET['page'] ) ? $_GET['page'] : '';
|
323 |
+
|
324 |
+
return self::SLUG === $page;
|
325 |
+
}
|
326 |
+
|
327 |
+
/**
|
328 |
+
* All possible plugin forms manipulation will be done here.
|
329 |
+
*
|
330 |
+
* @since 1.0.0
|
331 |
+
*/
|
332 |
+
public function process_actions() {
|
333 |
+
|
334 |
+
// Allow to process only own tabs.
|
335 |
+
if ( ! array_key_exists( $this->get_current_tab(), $this->get_pages() ) ) {
|
336 |
+
return;
|
337 |
+
}
|
338 |
+
|
339 |
+
// Process POST only if it exists.
|
340 |
+
if ( ! empty( $_POST ) ) {
|
341 |
+
if ( ! empty( $_POST['wp-mail-smtp'] ) ) {
|
342 |
+
$post = $_POST['wp-mail-smtp'];
|
343 |
+
} else {
|
344 |
+
$post = array();
|
345 |
+
}
|
346 |
+
|
347 |
+
$this->pages[ $this->get_current_tab() ]->process_post( $post );
|
348 |
+
}
|
349 |
+
|
350 |
+
// This won't do anything for most pages.
|
351 |
+
$this->pages[ $this->get_current_tab() ]->process_auth();
|
352 |
+
}
|
353 |
+
|
354 |
+
/**
|
355 |
+
* Add a link to Settings page of a plugin on Plugins page.
|
356 |
+
*
|
357 |
+
* @since 1.0.0
|
358 |
+
*
|
359 |
+
* @param array $links
|
360 |
+
* @param string $file
|
361 |
+
*
|
362 |
+
* @return mixed
|
363 |
+
*/
|
364 |
+
public function add_plugin_action_link( $links, $file ) {
|
365 |
+
|
366 |
+
if ( strpos( $file, 'wp-mail-smtp' ) === false ) {
|
367 |
+
return $links;
|
368 |
+
}
|
369 |
+
|
370 |
+
$settings_link = '<a href="' . $this->get_admin_page_url() . '">' . esc_html__( 'Settings', 'wp-mail-smtp' ) . '</a>';
|
371 |
+
|
372 |
+
array_unshift( $links, $settings_link );
|
373 |
+
|
374 |
+
return $links;
|
375 |
+
}
|
376 |
+
|
377 |
+
/**
|
378 |
+
* Get plugin admin area page URL.
|
379 |
+
*
|
380 |
+
* @since 1.0.0
|
381 |
+
*
|
382 |
+
* @return string
|
383 |
+
*/
|
384 |
+
public function get_admin_page_url() {
|
385 |
+
return add_query_arg(
|
386 |
+
'page',
|
387 |
+
self::SLUG,
|
388 |
+
admin_url( 'options-general.php' )
|
389 |
+
);
|
390 |
+
}
|
391 |
+
|
392 |
+
/**
|
393 |
+
* Remove all non-WP Mail SMTP plugin notices from plugin pages.
|
394 |
+
*
|
395 |
+
* @since 1.0.0
|
396 |
+
*/
|
397 |
+
public function hide_unrelated_notices() {
|
398 |
+
|
399 |
+
// Bail if we're not on a our screen or page.
|
400 |
+
if ( empty( $_REQUEST['page'] ) || strpos( $_REQUEST['page'], self::SLUG ) === false ) {
|
401 |
+
return;
|
402 |
+
}
|
403 |
+
|
404 |
+
global $wp_filter;
|
405 |
+
|
406 |
+
if ( ! empty( $wp_filter['user_admin_notices']->callbacks ) && is_array( $wp_filter['user_admin_notices']->callbacks ) ) {
|
407 |
+
foreach ( $wp_filter['user_admin_notices']->callbacks as $priority => $hooks ) {
|
408 |
+
foreach ( $hooks as $name => $arr ) {
|
409 |
+
if ( is_object( $arr['function'] ) && $arr['function'] instanceof \Closure ) {
|
410 |
+
unset( $wp_filter['user_admin_notices']->callbacks[ $priority ][ $name ] );
|
411 |
+
continue;
|
412 |
+
}
|
413 |
+
if ( ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) && strpos( strtolower( get_class( $arr['function'][0] ) ), 'wpmailsmtp' ) !== false ) {
|
414 |
+
continue;
|
415 |
+
}
|
416 |
+
if ( ! empty( $name ) && strpos( strtolower( $name ), 'wpmailsmtp' ) === false ) {
|
417 |
+
unset( $wp_filter['user_admin_notices']->callbacks[ $priority ][ $name ] );
|
418 |
+
}
|
419 |
+
}
|
420 |
+
}
|
421 |
+
}
|
422 |
+
|
423 |
+
if ( ! empty( $wp_filter['admin_notices']->callbacks ) && is_array( $wp_filter['admin_notices']->callbacks ) ) {
|
424 |
+
foreach ( $wp_filter['admin_notices']->callbacks as $priority => $hooks ) {
|
425 |
+
foreach ( $hooks as $name => $arr ) {
|
426 |
+
if ( is_object( $arr['function'] ) && $arr['function'] instanceof \Closure ) {
|
427 |
+
unset( $wp_filter['admin_notices']->callbacks[ $priority ][ $name ] );
|
428 |
+
continue;
|
429 |
+
}
|
430 |
+
if ( ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) && strpos( strtolower( get_class( $arr['function'][0] ) ), 'wpmailsmtp' ) !== false ) {
|
431 |
+
continue;
|
432 |
+
}
|
433 |
+
if ( ! empty( $name ) && strpos( strtolower( $name ), 'wpmailsmtp' ) === false ) {
|
434 |
+
unset( $wp_filter['admin_notices']->callbacks[ $priority ][ $name ] );
|
435 |
+
}
|
436 |
+
}
|
437 |
+
}
|
438 |
+
}
|
439 |
+
|
440 |
+
if ( ! empty( $wp_filter['all_admin_notices']->callbacks ) && is_array( $wp_filter['all_admin_notices']->callbacks ) ) {
|
441 |
+
foreach ( $wp_filter['all_admin_notices']->callbacks as $priority => $hooks ) {
|
442 |
+
foreach ( $hooks as $name => $arr ) {
|
443 |
+
if ( is_object( $arr['function'] ) && $arr['function'] instanceof \Closure ) {
|
444 |
+
unset( $wp_filter['all_admin_notices']->callbacks[ $priority ][ $name ] );
|
445 |
+
continue;
|
446 |
+
}
|
447 |
+
if ( ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) && strpos( strtolower( get_class( $arr['function'][0] ) ), 'wpmailsmtp' ) !== false ) {
|
448 |
+
continue;
|
449 |
+
}
|
450 |
+
if ( ! empty( $name ) && strpos( strtolower( $name ), 'wpmailsmtp' ) === false ) {
|
451 |
+
unset( $wp_filter['all_admin_notices']->callbacks[ $priority ][ $name ] );
|
452 |
+
}
|
453 |
+
}
|
454 |
+
}
|
455 |
+
}
|
456 |
+
}
|
457 |
+
}
|
src/Admin/PageAbstract.php
CHANGED
@@ -1,66 +1,66 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Admin;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Class PageAbstract.
|
7 |
-
*
|
8 |
-
* @since 1.0.0
|
9 |
-
*/
|
10 |
-
abstract class PageAbstract implements PageInterface {
|
11 |
-
|
12 |
-
/**
|
13 |
-
* @var string Slug of a tab.
|
14 |
-
*/
|
15 |
-
protected $slug;
|
16 |
-
|
17 |
-
/**
|
18 |
-
* @inheritdoc
|
19 |
-
*/
|
20 |
-
public function get_link() {
|
21 |
-
return esc_url(
|
22 |
-
add_query_arg(
|
23 |
-
'tab',
|
24 |
-
$this->slug,
|
25 |
-
admin_url( 'options-general.php?page=' . Area::SLUG )
|
26 |
-
)
|
27 |
-
);
|
28 |
-
}
|
29 |
-
|
30 |
-
/**
|
31 |
-
* Process tab form submission ($_POST ).
|
32 |
-
*
|
33 |
-
* @since 1.0.0
|
34 |
-
*
|
35 |
-
* @param array $data $_POST data specific for the plugin.
|
36 |
-
*/
|
37 |
-
public function process_post( $data ) {
|
38 |
-
}
|
39 |
-
|
40 |
-
/**
|
41 |
-
* Process tab & mailer specific Auth actions.
|
42 |
-
*
|
43 |
-
* @since 1.0.0
|
44 |
-
*/
|
45 |
-
public function process_auth() {
|
46 |
-
}
|
47 |
-
|
48 |
-
/**
|
49 |
-
* Print the nonce field for a specific tab.
|
50 |
-
*
|
51 |
-
* @since 1.0.0
|
52 |
-
*/
|
53 |
-
public function wp_nonce_field() {
|
54 |
-
wp_nonce_field( Area::SLUG . '-' . $this->slug );
|
55 |
-
}
|
56 |
-
|
57 |
-
/**
|
58 |
-
* Make sure that a user was referred from plugin admin page.
|
59 |
-
* To avoid security problems.
|
60 |
-
*
|
61 |
-
* @since 1.0.0
|
62 |
-
*/
|
63 |
-
public function check_admin_referer() {
|
64 |
-
check_admin_referer( Area::SLUG . '-' . $this->slug );
|
65 |
-
}
|
66 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Admin;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Class PageAbstract.
|
7 |
+
*
|
8 |
+
* @since 1.0.0
|
9 |
+
*/
|
10 |
+
abstract class PageAbstract implements PageInterface {
|
11 |
+
|
12 |
+
/**
|
13 |
+
* @var string Slug of a tab.
|
14 |
+
*/
|
15 |
+
protected $slug;
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @inheritdoc
|
19 |
+
*/
|
20 |
+
public function get_link() {
|
21 |
+
return esc_url(
|
22 |
+
add_query_arg(
|
23 |
+
'tab',
|
24 |
+
$this->slug,
|
25 |
+
admin_url( 'options-general.php?page=' . Area::SLUG )
|
26 |
+
)
|
27 |
+
);
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Process tab form submission ($_POST ).
|
32 |
+
*
|
33 |
+
* @since 1.0.0
|
34 |
+
*
|
35 |
+
* @param array $data $_POST data specific for the plugin.
|
36 |
+
*/
|
37 |
+
public function process_post( $data ) {
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Process tab & mailer specific Auth actions.
|
42 |
+
*
|
43 |
+
* @since 1.0.0
|
44 |
+
*/
|
45 |
+
public function process_auth() {
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Print the nonce field for a specific tab.
|
50 |
+
*
|
51 |
+
* @since 1.0.0
|
52 |
+
*/
|
53 |
+
public function wp_nonce_field() {
|
54 |
+
wp_nonce_field( Area::SLUG . '-' . $this->slug );
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Make sure that a user was referred from plugin admin page.
|
59 |
+
* To avoid security problems.
|
60 |
+
*
|
61 |
+
* @since 1.0.0
|
62 |
+
*/
|
63 |
+
public function check_admin_referer() {
|
64 |
+
check_admin_referer( Area::SLUG . '-' . $this->slug );
|
65 |
+
}
|
66 |
+
}
|
src/Admin/PageInterface.php
CHANGED
@@ -1,45 +1,45 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Admin;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Class PageInterface defines what should be in each page class.
|
7 |
-
*
|
8 |
-
* @since 1.0.0
|
9 |
-
*/
|
10 |
-
interface PageInterface {
|
11 |
-
|
12 |
-
/**
|
13 |
-
* URL to a tab.
|
14 |
-
*
|
15 |
-
* @since 1.0.0
|
16 |
-
*
|
17 |
-
* @return string
|
18 |
-
*/
|
19 |
-
public function get_link();
|
20 |
-
|
21 |
-
/**
|
22 |
-
* Title of a tab.
|
23 |
-
*
|
24 |
-
* @since 1.0.0
|
25 |
-
*
|
26 |
-
* @return string
|
27 |
-
*/
|
28 |
-
public function get_title();
|
29 |
-
|
30 |
-
/**
|
31 |
-
* Link label of a tab.
|
32 |
-
*
|
33 |
-
* @since 1.0.0
|
34 |
-
*
|
35 |
-
* @return string
|
36 |
-
*/
|
37 |
-
public function get_label();
|
38 |
-
|
39 |
-
/**
|
40 |
-
* Tab content.
|
41 |
-
*
|
42 |
-
* @since 1.0.0
|
43 |
-
*/
|
44 |
-
public function display();
|
45 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Admin;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Class PageInterface defines what should be in each page class.
|
7 |
+
*
|
8 |
+
* @since 1.0.0
|
9 |
+
*/
|
10 |
+
interface PageInterface {
|
11 |
+
|
12 |
+
/**
|
13 |
+
* URL to a tab.
|
14 |
+
*
|
15 |
+
* @since 1.0.0
|
16 |
+
*
|
17 |
+
* @return string
|
18 |
+
*/
|
19 |
+
public function get_link();
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Title of a tab.
|
23 |
+
*
|
24 |
+
* @since 1.0.0
|
25 |
+
*
|
26 |
+
* @return string
|
27 |
+
*/
|
28 |
+
public function get_title();
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Link label of a tab.
|
32 |
+
*
|
33 |
+
* @since 1.0.0
|
34 |
+
*
|
35 |
+
* @return string
|
36 |
+
*/
|
37 |
+
public function get_label();
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Tab content.
|
41 |
+
*
|
42 |
+
* @since 1.0.0
|
43 |
+
*/
|
44 |
+
public function display();
|
45 |
+
}
|
src/Admin/Pages/Auth.php
CHANGED
@@ -1,56 +1,56 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Admin\Pages;
|
4 |
-
|
5 |
-
use WPMailSMTP\Options;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Class Auth.
|
9 |
-
*
|
10 |
-
* @since 1.0.0
|
11 |
-
*/
|
12 |
-
class Auth {
|
13 |
-
|
14 |
-
/**
|
15 |
-
* @var string Slug of a tab.
|
16 |
-
*/
|
17 |
-
protected $slug = 'auth';
|
18 |
-
|
19 |
-
/**
|
20 |
-
* Launch mailer specific Auth logic.
|
21 |
-
*
|
22 |
-
* @since 1.0.0
|
23 |
-
*/
|
24 |
-
public function process_auth() {
|
25 |
-
|
26 |
-
$auth = wp_mail_smtp()->get_providers()->get_auth( Options::init()->get( 'mail', 'mailer' ) );
|
27 |
-
|
28 |
-
$auth->process();
|
29 |
-
}
|
30 |
-
|
31 |
-
/**
|
32 |
-
* Return nothing, as we don't need this functionality.
|
33 |
-
*
|
34 |
-
* @since 1.0.0
|
35 |
-
*/
|
36 |
-
public function get_label() {
|
37 |
-
return '';
|
38 |
-
}
|
39 |
-
|
40 |
-
/**
|
41 |
-
* Return nothing, as we don't need this functionality.
|
42 |
-
*
|
43 |
-
* @since 1.0.0
|
44 |
-
*/
|
45 |
-
public function get_title() {
|
46 |
-
return '';
|
47 |
-
}
|
48 |
-
|
49 |
-
/**
|
50 |
-
* Do nothing, as we don't need this functionality.
|
51 |
-
*
|
52 |
-
* @since 1.0.0
|
53 |
-
*/
|
54 |
-
public function display() {
|
55 |
-
}
|
56 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Admin\Pages;
|
4 |
+
|
5 |
+
use WPMailSMTP\Options;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class Auth.
|
9 |
+
*
|
10 |
+
* @since 1.0.0
|
11 |
+
*/
|
12 |
+
class Auth {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var string Slug of a tab.
|
16 |
+
*/
|
17 |
+
protected $slug = 'auth';
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Launch mailer specific Auth logic.
|
21 |
+
*
|
22 |
+
* @since 1.0.0
|
23 |
+
*/
|
24 |
+
public function process_auth() {
|
25 |
+
|
26 |
+
$auth = wp_mail_smtp()->get_providers()->get_auth( Options::init()->get( 'mail', 'mailer' ) );
|
27 |
+
|
28 |
+
$auth->process();
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Return nothing, as we don't need this functionality.
|
33 |
+
*
|
34 |
+
* @since 1.0.0
|
35 |
+
*/
|
36 |
+
public function get_label() {
|
37 |
+
return '';
|
38 |
+
}
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Return nothing, as we don't need this functionality.
|
42 |
+
*
|
43 |
+
* @since 1.0.0
|
44 |
+
*/
|
45 |
+
public function get_title() {
|
46 |
+
return '';
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Do nothing, as we don't need this functionality.
|
51 |
+
*
|
52 |
+
* @since 1.0.0
|
53 |
+
*/
|
54 |
+
public function display() {
|
55 |
+
}
|
56 |
+
}
|
src/Admin/Pages/Misc.php
CHANGED
@@ -1,99 +1,99 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Admin\Pages;
|
4 |
-
|
5 |
-
use WPMailSMTP\Admin\PageAbstract;
|
6 |
-
use WPMailSMTP\Options;
|
7 |
-
use WPMailSMTP\WP;
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Class Misc is part of Area, displays different plugin-related settings of the plugin (not related to emails).
|
11 |
-
*
|
12 |
-
* @since 1.0.0
|
13 |
-
*/
|
14 |
-
class Misc extends PageAbstract {
|
15 |
-
/**
|
16 |
-
* @var string Slug of a tab.
|
17 |
-
*/
|
18 |
-
protected $slug = 'misc';
|
19 |
-
|
20 |
-
/**
|
21 |
-
* @inheritdoc
|
22 |
-
*/
|
23 |
-
public function get_label() {
|
24 |
-
return esc_html__( 'Misc', 'wp-mail-smtp' );
|
25 |
-
}
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @inheritdoc
|
29 |
-
*/
|
30 |
-
public function get_title() {
|
31 |
-
return $this->get_label();
|
32 |
-
}
|
33 |
-
|
34 |
-
/**
|
35 |
-
* @inheritdoc
|
36 |
-
*/
|
37 |
-
public function display() {
|
38 |
-
|
39 |
-
$options = new Options();
|
40 |
-
?>
|
41 |
-
|
42 |
-
<form method="POST" action="">
|
43 |
-
<?php $this->wp_nonce_field(); ?>
|
44 |
-
|
45 |
-
<!-- General Section Title -->
|
46 |
-
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading no-desc" id="wp-mail-smtp-setting-row-email-heading">
|
47 |
-
<div class="wp-mail-smtp-setting-field">
|
48 |
-
<h2><?php esc_html_e( 'General', 'wp-mail-smtp' ); ?></h2>
|
49 |
-
</div>
|
50 |
-
</div>
|
51 |
-
|
52 |
-
<!-- Hide Announcements -->
|
53 |
-
<div id="wp-mail-smtp-setting-row-am_notifications_hidden" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox wp-mail-smtp-clear">
|
54 |
-
<div class="wp-mail-smtp-setting-label">
|
55 |
-
<label for="wp-mail-smtp-setting-am_notifications_hidden"><?php esc_html_e( 'Hide Announcements', 'wp-mail-smtp' ); ?></label>
|
56 |
-
</div>
|
57 |
-
<div class="wp-mail-smtp-setting-field">
|
58 |
-
<input name="wp-mail-smtp[general][am_notifications_hidden]" type="checkbox"
|
59 |
-
value="true" <?php checked( true, $options->get( 'general', 'am_notifications_hidden' ) ); ?>
|
60 |
-
id="wp-mail-smtp-setting-am_notifications_hidden"
|
61 |
-
/>
|
62 |
-
<label for="wp-mail-smtp-setting-am_notifications_hidden"><?php esc_html_e( 'Check this if you would like to hide plugin announcements and update details.', 'wp-mail-smtp' ); ?></label>
|
63 |
-
</div>
|
64 |
-
</div>
|
65 |
-
|
66 |
-
<p class="wp-mail-smtp-submit">
|
67 |
-
<button type="submit" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-orange"><?php esc_html_e( 'Save Settings', 'wp-mail-smtp' ); ?></button>
|
68 |
-
</p>
|
69 |
-
|
70 |
-
</form>
|
71 |
-
|
72 |
-
<?php
|
73 |
-
}
|
74 |
-
|
75 |
-
/**
|
76 |
-
* @inheritdoc
|
77 |
-
*/
|
78 |
-
public function process_post( $data ) {
|
79 |
-
|
80 |
-
$this->check_admin_referer();
|
81 |
-
|
82 |
-
$options = new Options();
|
83 |
-
|
84 |
-
// Unchecked checkbox doesn't exist in $_POST, so we need to ensure we actually have it.
|
85 |
-
if ( empty( $data['general']['am_notifications_hidden'] ) ) {
|
86 |
-
$data['general']['am_notifications_hidden'] = false;
|
87 |
-
}
|
88 |
-
|
89 |
-
$to_save = array_merge( $options->get_all(), $data );
|
90 |
-
|
91 |
-
// All the sanitization is done there.
|
92 |
-
$options->set( $to_save );
|
93 |
-
|
94 |
-
WP::add_admin_notice(
|
95 |
-
esc_html__( 'Settings were successfully saved.', 'wp-mail-smtp' ),
|
96 |
-
WP::ADMIN_NOTICE_SUCCESS
|
97 |
-
);
|
98 |
-
}
|
99 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Admin\Pages;
|
4 |
+
|
5 |
+
use WPMailSMTP\Admin\PageAbstract;
|
6 |
+
use WPMailSMTP\Options;
|
7 |
+
use WPMailSMTP\WP;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Class Misc is part of Area, displays different plugin-related settings of the plugin (not related to emails).
|
11 |
+
*
|
12 |
+
* @since 1.0.0
|
13 |
+
*/
|
14 |
+
class Misc extends PageAbstract {
|
15 |
+
/**
|
16 |
+
* @var string Slug of a tab.
|
17 |
+
*/
|
18 |
+
protected $slug = 'misc';
|
19 |
+
|
20 |
+
/**
|
21 |
+
* @inheritdoc
|
22 |
+
*/
|
23 |
+
public function get_label() {
|
24 |
+
return esc_html__( 'Misc', 'wp-mail-smtp' );
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @inheritdoc
|
29 |
+
*/
|
30 |
+
public function get_title() {
|
31 |
+
return $this->get_label();
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* @inheritdoc
|
36 |
+
*/
|
37 |
+
public function display() {
|
38 |
+
|
39 |
+
$options = new Options();
|
40 |
+
?>
|
41 |
+
|
42 |
+
<form method="POST" action="">
|
43 |
+
<?php $this->wp_nonce_field(); ?>
|
44 |
+
|
45 |
+
<!-- General Section Title -->
|
46 |
+
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading no-desc" id="wp-mail-smtp-setting-row-email-heading">
|
47 |
+
<div class="wp-mail-smtp-setting-field">
|
48 |
+
<h2><?php esc_html_e( 'General', 'wp-mail-smtp' ); ?></h2>
|
49 |
+
</div>
|
50 |
+
</div>
|
51 |
+
|
52 |
+
<!-- Hide Announcements -->
|
53 |
+
<div id="wp-mail-smtp-setting-row-am_notifications_hidden" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox wp-mail-smtp-clear">
|
54 |
+
<div class="wp-mail-smtp-setting-label">
|
55 |
+
<label for="wp-mail-smtp-setting-am_notifications_hidden"><?php esc_html_e( 'Hide Announcements', 'wp-mail-smtp' ); ?></label>
|
56 |
+
</div>
|
57 |
+
<div class="wp-mail-smtp-setting-field">
|
58 |
+
<input name="wp-mail-smtp[general][am_notifications_hidden]" type="checkbox"
|
59 |
+
value="true" <?php checked( true, $options->get( 'general', 'am_notifications_hidden' ) ); ?>
|
60 |
+
id="wp-mail-smtp-setting-am_notifications_hidden"
|
61 |
+
/>
|
62 |
+
<label for="wp-mail-smtp-setting-am_notifications_hidden"><?php esc_html_e( 'Check this if you would like to hide plugin announcements and update details.', 'wp-mail-smtp' ); ?></label>
|
63 |
+
</div>
|
64 |
+
</div>
|
65 |
+
|
66 |
+
<p class="wp-mail-smtp-submit">
|
67 |
+
<button type="submit" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-orange"><?php esc_html_e( 'Save Settings', 'wp-mail-smtp' ); ?></button>
|
68 |
+
</p>
|
69 |
+
|
70 |
+
</form>
|
71 |
+
|
72 |
+
<?php
|
73 |
+
}
|
74 |
+
|
75 |
+
/**
|
76 |
+
* @inheritdoc
|
77 |
+
*/
|
78 |
+
public function process_post( $data ) {
|
79 |
+
|
80 |
+
$this->check_admin_referer();
|
81 |
+
|
82 |
+
$options = new Options();
|
83 |
+
|
84 |
+
// Unchecked checkbox doesn't exist in $_POST, so we need to ensure we actually have it.
|
85 |
+
if ( empty( $data['general']['am_notifications_hidden'] ) ) {
|
86 |
+
$data['general']['am_notifications_hidden'] = false;
|
87 |
+
}
|
88 |
+
|
89 |
+
$to_save = array_merge( $options->get_all(), $data );
|
90 |
+
|
91 |
+
// All the sanitization is done there.
|
92 |
+
$options->set( $to_save );
|
93 |
+
|
94 |
+
WP::add_admin_notice(
|
95 |
+
esc_html__( 'Settings were successfully saved.', 'wp-mail-smtp' ),
|
96 |
+
WP::ADMIN_NOTICE_SUCCESS
|
97 |
+
);
|
98 |
+
}
|
99 |
+
}
|
src/Admin/Pages/Settings.php
CHANGED
@@ -1,236 +1,236 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Admin\Pages;
|
4 |
-
|
5 |
-
use WPMailSMTP\Admin\PageAbstract;
|
6 |
-
use WPMailSMTP\Options;
|
7 |
-
use WPMailSMTP\WP;
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Class Settings is part of Area, displays general settings of the plugin.
|
11 |
-
*
|
12 |
-
* @since 1.0.0
|
13 |
-
*/
|
14 |
-
class Settings extends PageAbstract {
|
15 |
-
|
16 |
-
/**
|
17 |
-
* @var string Slug of a tab.
|
18 |
-
*/
|
19 |
-
protected $slug = 'settings';
|
20 |
-
|
21 |
-
/**
|
22 |
-
* @inheritdoc
|
23 |
-
*/
|
24 |
-
public function get_label() {
|
25 |
-
return esc_html__( 'Settings', 'wp-mail-smtp' );
|
26 |
-
}
|
27 |
-
|
28 |
-
/**
|
29 |
-
* @inheritdoc
|
30 |
-
*/
|
31 |
-
public function get_title() {
|
32 |
-
return $this->get_label();
|
33 |
-
}
|
34 |
-
|
35 |
-
/**
|
36 |
-
* @inheritdoc
|
37 |
-
*/
|
38 |
-
public function display() {
|
39 |
-
|
40 |
-
$options = new Options();
|
41 |
-
$mailer = $options->get( 'mail', 'mailer' );
|
42 |
-
?>
|
43 |
-
|
44 |
-
<form method="POST" action="">
|
45 |
-
<?php $this->wp_nonce_field(); ?>
|
46 |
-
|
47 |
-
<!-- Mail Section Title -->
|
48 |
-
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading no-desc" id="wp-mail-smtp-setting-row-email-heading">
|
49 |
-
<div class="wp-mail-smtp-setting-field">
|
50 |
-
<h2><?php esc_html_e( 'Mail', 'wp-mail-smtp' ); ?></h2>
|
51 |
-
</div>
|
52 |
-
</div>
|
53 |
-
|
54 |
-
<!-- From Email -->
|
55 |
-
<div id="wp-mail-smtp-setting-row-from_email" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-email wp-mail-smtp-clear">
|
56 |
-
<div class="wp-mail-smtp-setting-label">
|
57 |
-
<label for="wp-mail-smtp-setting-from_email"><?php esc_html_e( 'From Email', 'wp-mail-smtp' ); ?></label>
|
58 |
-
</div>
|
59 |
-
<div class="wp-mail-smtp-setting-field">
|
60 |
-
<input name="wp-mail-smtp[mail][from_email]" type="email"
|
61 |
-
value="<?php echo esc_attr( $options->get( 'mail', 'from_email' ) ); ?>"
|
62 |
-
<?php echo $options->is_const_defined( 'mail', 'from_email' ) ? 'disabled' : ''; ?>
|
63 |
-
id="wp-mail-smtp-setting-from_email" spellcheck="false"
|
64 |
-
/>
|
65 |
-
<p class="desc">
|
66 |
-
<?php esc_html_e( 'You can specify the email address that emails should be sent from.', 'wp-mail-smtp' ); ?><br/>
|
67 |
-
<?php
|
68 |
-
printf(
|
69 |
-
/* translators: %s - default email address. */
|
70 |
-
esc_html__( 'If you leave this blank, the default one will be used: %s.', 'wp-mail-smtp' ),
|
71 |
-
'<code>' . wp_mail_smtp()->get_processor()->get_default_email() . '</code>'
|
72 |
-
);
|
73 |
-
?>
|
74 |
-
</p>
|
75 |
-
<p class="desc">
|
76 |
-
<?php esc_html_e( 'Please note if you are sending using an email provider (Gmail, Yahoo, Hotmail, Outlook.com, etc) this setting should be your email address for that account.', 'wp-mail-smtp' ); ?>
|
77 |
-
</p>
|
78 |
-
</div>
|
79 |
-
</div>
|
80 |
-
|
81 |
-
<!-- From Name -->
|
82 |
-
<div id="wp-mail-smtp-setting-row-from_name" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
83 |
-
<div class="wp-mail-smtp-setting-label">
|
84 |
-
<label for="wp-mail-smtp-setting-from_name"><?php esc_html_e( 'From Name', 'wp-mail-smtp' ); ?></label>
|
85 |
-
</div>
|
86 |
-
<div class="wp-mail-smtp-setting-field">
|
87 |
-
<input name="wp-mail-smtp[mail][from_name]" type="text"
|
88 |
-
value="<?php echo esc_attr( $options->get( 'mail', 'from_name' ) ); ?>"
|
89 |
-
<?php echo $options->is_const_defined( 'mail', 'from_name' ) ? 'disabled' : ''; ?>
|
90 |
-
id="wp-mail-smtp-setting-from-name" spellcheck="false"
|
91 |
-
/>
|
92 |
-
<p class="desc">
|
93 |
-
<?php esc_html_e( 'You can specify the name that emails should be sent from.', 'wp-mail-smtp' ); ?><br/>
|
94 |
-
<?php
|
95 |
-
printf(
|
96 |
-
/* translators: %s - WordPress. */
|
97 |
-
esc_html__( 'If you leave this blank, the emails will be sent from %s.', 'wp-mail-smtp' ),
|
98 |
-
'<code>WordPress</code>'
|
99 |
-
);
|
100 |
-
?>
|
101 |
-
</p>
|
102 |
-
</div>
|
103 |
-
</div>
|
104 |
-
|
105 |
-
<!-- Mailer -->
|
106 |
-
<div id="wp-mail-smtp-setting-row-mailer" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-mailer wp-mail-smtp-clear">
|
107 |
-
<div class="wp-mail-smtp-setting-label">
|
108 |
-
<label for="wp-mail-smtp-setting-mailer"><?php esc_html_e( 'Mailer', 'wp-mail-smtp' ); ?></label>
|
109 |
-
</div>
|
110 |
-
<div class="wp-mail-smtp-setting-field">
|
111 |
-
<div class="wp-mail-smtp-mailers">
|
112 |
-
|
113 |
-
<?php foreach ( wp_mail_smtp()->get_providers()->get_options_all() as $provider ) : ?>
|
114 |
-
|
115 |
-
<div class="wp-mail-smtp-mailer <?php echo $mailer === $provider->get_slug() ? 'active' : ''; ?>">
|
116 |
-
<div class="wp-mail-smtp-mailer-image">
|
117 |
-
<img src="<?php echo esc_url( $provider->get_logo_url() ); ?>"
|
118 |
-
alt="<?php echo esc_attr( $provider->get_title() ); ?>">
|
119 |
-
</div>
|
120 |
-
|
121 |
-
<div class="wp-mail-smtp-mailer-text">
|
122 |
-
<input id="wp-mail-smtp-setting-mailer-<?php echo esc_attr( $provider->get_slug() ); ?>"
|
123 |
-
type="radio" name="wp-mail-smtp[mail][mailer]"
|
124 |
-
value="<?php echo esc_attr( $provider->get_slug() ); ?>"
|
125 |
-
<?php checked( $provider->get_slug(), $mailer ); ?>
|
126 |
-
<?php echo $options->is_const_defined( 'mail', 'mailer' ) ? 'disabled' : ''; ?>
|
127 |
-
/>
|
128 |
-
<label for="wp-mail-smtp-setting-mailer-<?php echo esc_attr( $provider->get_slug() ); ?>"><?php echo $provider->get_title(); ?></label>
|
129 |
-
</div>
|
130 |
-
</div>
|
131 |
-
|
132 |
-
<?php endforeach; ?>
|
133 |
-
|
134 |
-
</div>
|
135 |
-
</div>
|
136 |
-
</div>
|
137 |
-
|
138 |
-
<!-- Return Path -->
|
139 |
-
<div id="wp-mail-smtp-setting-row-return_path" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox wp-mail-smtp-clear">
|
140 |
-
<div class="wp-mail-smtp-setting-label">
|
141 |
-
<label for="wp-mail-smtp-setting-return_path"><?php esc_html_e( 'Return Path', 'wp-mail-smtp' ); ?></label>
|
142 |
-
</div>
|
143 |
-
<div class="wp-mail-smtp-setting-field">
|
144 |
-
<input name="wp-mail-smtp[mail][return_path]" type="checkbox"
|
145 |
-
value="true" <?php checked( true, $options->get( 'mail', 'return_path' ) ); ?>
|
146 |
-
<?php echo $options->is_const_defined( 'mail', 'return_path' ) ? 'disabled' : ''; ?>
|
147 |
-
id="wp-mail-smtp-setting-return_path"
|
148 |
-
/>
|
149 |
-
<label for="wp-mail-smtp-setting-return_path"><?php esc_html_e( 'Set the return-path to match the From Email', 'wp-mail-smtp' ); ?></label></label>
|
150 |
-
<p class="desc">
|
151 |
-
<?php esc_html_e( 'Return Path indicates where non-delivery receipts - or bounce messages - are to be sent.', 'wp-mail-smtp' ); ?><br/>
|
152 |
-
<?php esc_html_e( 'If unchecked bounce messages may be lost.', 'wp-mail-smtp' ); ?>
|
153 |
-
</p>
|
154 |
-
</div>
|
155 |
-
</div>
|
156 |
-
|
157 |
-
<!-- Mailer Options -->
|
158 |
-
<div class="wp-mail-smtp-mailer-options">
|
159 |
-
<?php foreach ( wp_mail_smtp()->get_providers()->get_options_all() as $provider ) : ?>
|
160 |
-
|
161 |
-
<div class="wp-mail-smtp-mailer-option wp-mail-smtp-mailer-option-<?php echo esc_attr( $provider->get_slug() ); ?> <?php echo $mailer === $provider->get_slug() ? 'active' : 'hidden'; ?>">
|
162 |
-
|
163 |
-
<!-- Mailer Option Title -->
|
164 |
-
<?php $provider_desc = $provider->get_description(); ?>
|
165 |
-
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading <?php empty( $provider_desc ) ? 'no-desc' : ''; ?>" id="wp-mail-smtp-setting-row-email-heading">
|
166 |
-
<div class="wp-mail-smtp-setting-field">
|
167 |
-
<h2><?php echo $provider->get_title(); ?></h2>
|
168 |
-
<?php if ( ! empty( $provider_desc ) ) : ?>
|
169 |
-
<p class="desc"><?php echo $provider_desc; ?></p>
|
170 |
-
<?php endif; ?>
|
171 |
-
</div>
|
172 |
-
</div>
|
173 |
-
|
174 |
-
<?php $provider->display_options(); ?>
|
175 |
-
</div>
|
176 |
-
|
177 |
-
<?php endforeach; ?>
|
178 |
-
|
179 |
-
</div>
|
180 |
-
|
181 |
-
<p class="wp-mail-smtp-submit">
|
182 |
-
<button type="submit" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-orange"><?php esc_html_e( 'Save Settings', 'wp-mail-smtp' ); ?></button>
|
183 |
-
</p>
|
184 |
-
|
185 |
-
</form>
|
186 |
-
|
187 |
-
<?php
|
188 |
-
}
|
189 |
-
|
190 |
-
/**
|
191 |
-
* @inheritdoc
|
192 |
-
*/
|
193 |
-
public function process_post( $data ) {
|
194 |
-
|
195 |
-
$this->check_admin_referer();
|
196 |
-
|
197 |
-
$options = new Options();
|
198 |
-
$old_opt = $options->get_all();
|
199 |
-
|
200 |
-
$to_redirect = false;
|
201 |
-
|
202 |
-
// Old and new Gmail client id/secret values are different - we need to invalidate tokens and scroll to Auth button.
|
203 |
-
if (
|
204 |
-
$options->get( 'mail', 'mailer' ) === 'gmail' &&
|
205 |
-
(
|
206 |
-
$options->get( 'gmail', 'client_id' ) !== $data['gmail']['client_id'] ||
|
207 |
-
$options->get( 'gmail', 'client_secret' ) !== $data['gmail']['client_secret']
|
208 |
-
)
|
209 |
-
) {
|
210 |
-
unset( $old_opt['gmail'] );
|
211 |
-
|
212 |
-
if (
|
213 |
-
! empty( $data['gmail']['client_id'] ) &&
|
214 |
-
! empty( $data['gmail']['client_secret'] )
|
215 |
-
) {
|
216 |
-
$to_redirect = true;
|
217 |
-
}
|
218 |
-
}
|
219 |
-
|
220 |
-
// New gmail clients data will be added from new $data, except the old access/refresh_token.
|
221 |
-
$to_save = array_merge( $old_opt, $data );
|
222 |
-
|
223 |
-
// All the sanitization is done there.
|
224 |
-
$options->set( $to_save );
|
225 |
-
|
226 |
-
if ( $to_redirect ) {
|
227 |
-
wp_redirect( $_POST['_wp_http_referer'] . '#wp-mail-smtp-setting-row-gmail-authorize' );
|
228 |
-
exit;
|
229 |
-
}
|
230 |
-
|
231 |
-
WP::add_admin_notice(
|
232 |
-
esc_html__( 'Settings were successfully saved.', 'wp-mail-smtp' ),
|
233 |
-
WP::ADMIN_NOTICE_SUCCESS
|
234 |
-
);
|
235 |
-
}
|
236 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Admin\Pages;
|
4 |
+
|
5 |
+
use WPMailSMTP\Admin\PageAbstract;
|
6 |
+
use WPMailSMTP\Options;
|
7 |
+
use WPMailSMTP\WP;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Class Settings is part of Area, displays general settings of the plugin.
|
11 |
+
*
|
12 |
+
* @since 1.0.0
|
13 |
+
*/
|
14 |
+
class Settings extends PageAbstract {
|
15 |
+
|
16 |
+
/**
|
17 |
+
* @var string Slug of a tab.
|
18 |
+
*/
|
19 |
+
protected $slug = 'settings';
|
20 |
+
|
21 |
+
/**
|
22 |
+
* @inheritdoc
|
23 |
+
*/
|
24 |
+
public function get_label() {
|
25 |
+
return esc_html__( 'Settings', 'wp-mail-smtp' );
|
26 |
+
}
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @inheritdoc
|
30 |
+
*/
|
31 |
+
public function get_title() {
|
32 |
+
return $this->get_label();
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* @inheritdoc
|
37 |
+
*/
|
38 |
+
public function display() {
|
39 |
+
|
40 |
+
$options = new Options();
|
41 |
+
$mailer = $options->get( 'mail', 'mailer' );
|
42 |
+
?>
|
43 |
+
|
44 |
+
<form method="POST" action="">
|
45 |
+
<?php $this->wp_nonce_field(); ?>
|
46 |
+
|
47 |
+
<!-- Mail Section Title -->
|
48 |
+
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading no-desc" id="wp-mail-smtp-setting-row-email-heading">
|
49 |
+
<div class="wp-mail-smtp-setting-field">
|
50 |
+
<h2><?php esc_html_e( 'Mail', 'wp-mail-smtp' ); ?></h2>
|
51 |
+
</div>
|
52 |
+
</div>
|
53 |
+
|
54 |
+
<!-- From Email -->
|
55 |
+
<div id="wp-mail-smtp-setting-row-from_email" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-email wp-mail-smtp-clear">
|
56 |
+
<div class="wp-mail-smtp-setting-label">
|
57 |
+
<label for="wp-mail-smtp-setting-from_email"><?php esc_html_e( 'From Email', 'wp-mail-smtp' ); ?></label>
|
58 |
+
</div>
|
59 |
+
<div class="wp-mail-smtp-setting-field">
|
60 |
+
<input name="wp-mail-smtp[mail][from_email]" type="email"
|
61 |
+
value="<?php echo esc_attr( $options->get( 'mail', 'from_email' ) ); ?>"
|
62 |
+
<?php echo $options->is_const_defined( 'mail', 'from_email' ) ? 'disabled' : ''; ?>
|
63 |
+
id="wp-mail-smtp-setting-from_email" spellcheck="false"
|
64 |
+
/>
|
65 |
+
<p class="desc">
|
66 |
+
<?php esc_html_e( 'You can specify the email address that emails should be sent from.', 'wp-mail-smtp' ); ?><br/>
|
67 |
+
<?php
|
68 |
+
printf(
|
69 |
+
/* translators: %s - default email address. */
|
70 |
+
esc_html__( 'If you leave this blank, the default one will be used: %s.', 'wp-mail-smtp' ),
|
71 |
+
'<code>' . wp_mail_smtp()->get_processor()->get_default_email() . '</code>'
|
72 |
+
);
|
73 |
+
?>
|
74 |
+
</p>
|
75 |
+
<p class="desc">
|
76 |
+
<?php esc_html_e( 'Please note if you are sending using an email provider (Gmail, Yahoo, Hotmail, Outlook.com, etc) this setting should be your email address for that account.', 'wp-mail-smtp' ); ?>
|
77 |
+
</p>
|
78 |
+
</div>
|
79 |
+
</div>
|
80 |
+
|
81 |
+
<!-- From Name -->
|
82 |
+
<div id="wp-mail-smtp-setting-row-from_name" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
83 |
+
<div class="wp-mail-smtp-setting-label">
|
84 |
+
<label for="wp-mail-smtp-setting-from_name"><?php esc_html_e( 'From Name', 'wp-mail-smtp' ); ?></label>
|
85 |
+
</div>
|
86 |
+
<div class="wp-mail-smtp-setting-field">
|
87 |
+
<input name="wp-mail-smtp[mail][from_name]" type="text"
|
88 |
+
value="<?php echo esc_attr( $options->get( 'mail', 'from_name' ) ); ?>"
|
89 |
+
<?php echo $options->is_const_defined( 'mail', 'from_name' ) ? 'disabled' : ''; ?>
|
90 |
+
id="wp-mail-smtp-setting-from-name" spellcheck="false"
|
91 |
+
/>
|
92 |
+
<p class="desc">
|
93 |
+
<?php esc_html_e( 'You can specify the name that emails should be sent from.', 'wp-mail-smtp' ); ?><br/>
|
94 |
+
<?php
|
95 |
+
printf(
|
96 |
+
/* translators: %s - WordPress. */
|
97 |
+
esc_html__( 'If you leave this blank, the emails will be sent from %s.', 'wp-mail-smtp' ),
|
98 |
+
'<code>WordPress</code>'
|
99 |
+
);
|
100 |
+
?>
|
101 |
+
</p>
|
102 |
+
</div>
|
103 |
+
</div>
|
104 |
+
|
105 |
+
<!-- Mailer -->
|
106 |
+
<div id="wp-mail-smtp-setting-row-mailer" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-mailer wp-mail-smtp-clear">
|
107 |
+
<div class="wp-mail-smtp-setting-label">
|
108 |
+
<label for="wp-mail-smtp-setting-mailer"><?php esc_html_e( 'Mailer', 'wp-mail-smtp' ); ?></label>
|
109 |
+
</div>
|
110 |
+
<div class="wp-mail-smtp-setting-field">
|
111 |
+
<div class="wp-mail-smtp-mailers">
|
112 |
+
|
113 |
+
<?php foreach ( wp_mail_smtp()->get_providers()->get_options_all() as $provider ) : ?>
|
114 |
+
|
115 |
+
<div class="wp-mail-smtp-mailer <?php echo $mailer === $provider->get_slug() ? 'active' : ''; ?>">
|
116 |
+
<div class="wp-mail-smtp-mailer-image">
|
117 |
+
<img src="<?php echo esc_url( $provider->get_logo_url() ); ?>"
|
118 |
+
alt="<?php echo esc_attr( $provider->get_title() ); ?>">
|
119 |
+
</div>
|
120 |
+
|
121 |
+
<div class="wp-mail-smtp-mailer-text">
|
122 |
+
<input id="wp-mail-smtp-setting-mailer-<?php echo esc_attr( $provider->get_slug() ); ?>"
|
123 |
+
type="radio" name="wp-mail-smtp[mail][mailer]"
|
124 |
+
value="<?php echo esc_attr( $provider->get_slug() ); ?>"
|
125 |
+
<?php checked( $provider->get_slug(), $mailer ); ?>
|
126 |
+
<?php echo $options->is_const_defined( 'mail', 'mailer' ) ? 'disabled' : ''; ?>
|
127 |
+
/>
|
128 |
+
<label for="wp-mail-smtp-setting-mailer-<?php echo esc_attr( $provider->get_slug() ); ?>"><?php echo $provider->get_title(); ?></label>
|
129 |
+
</div>
|
130 |
+
</div>
|
131 |
+
|
132 |
+
<?php endforeach; ?>
|
133 |
+
|
134 |
+
</div>
|
135 |
+
</div>
|
136 |
+
</div>
|
137 |
+
|
138 |
+
<!-- Return Path -->
|
139 |
+
<div id="wp-mail-smtp-setting-row-return_path" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox wp-mail-smtp-clear">
|
140 |
+
<div class="wp-mail-smtp-setting-label">
|
141 |
+
<label for="wp-mail-smtp-setting-return_path"><?php esc_html_e( 'Return Path', 'wp-mail-smtp' ); ?></label>
|
142 |
+
</div>
|
143 |
+
<div class="wp-mail-smtp-setting-field">
|
144 |
+
<input name="wp-mail-smtp[mail][return_path]" type="checkbox"
|
145 |
+
value="true" <?php checked( true, $options->get( 'mail', 'return_path' ) ); ?>
|
146 |
+
<?php echo $options->is_const_defined( 'mail', 'return_path' ) ? 'disabled' : ''; ?>
|
147 |
+
id="wp-mail-smtp-setting-return_path"
|
148 |
+
/>
|
149 |
+
<label for="wp-mail-smtp-setting-return_path"><?php esc_html_e( 'Set the return-path to match the From Email', 'wp-mail-smtp' ); ?></label></label>
|
150 |
+
<p class="desc">
|
151 |
+
<?php esc_html_e( 'Return Path indicates where non-delivery receipts - or bounce messages - are to be sent.', 'wp-mail-smtp' ); ?><br/>
|
152 |
+
<?php esc_html_e( 'If unchecked bounce messages may be lost.', 'wp-mail-smtp' ); ?>
|
153 |
+
</p>
|
154 |
+
</div>
|
155 |
+
</div>
|
156 |
+
|
157 |
+
<!-- Mailer Options -->
|
158 |
+
<div class="wp-mail-smtp-mailer-options">
|
159 |
+
<?php foreach ( wp_mail_smtp()->get_providers()->get_options_all() as $provider ) : ?>
|
160 |
+
|
161 |
+
<div class="wp-mail-smtp-mailer-option wp-mail-smtp-mailer-option-<?php echo esc_attr( $provider->get_slug() ); ?> <?php echo $mailer === $provider->get_slug() ? 'active' : 'hidden'; ?>">
|
162 |
+
|
163 |
+
<!-- Mailer Option Title -->
|
164 |
+
<?php $provider_desc = $provider->get_description(); ?>
|
165 |
+
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading <?php empty( $provider_desc ) ? 'no-desc' : ''; ?>" id="wp-mail-smtp-setting-row-email-heading">
|
166 |
+
<div class="wp-mail-smtp-setting-field">
|
167 |
+
<h2><?php echo $provider->get_title(); ?></h2>
|
168 |
+
<?php if ( ! empty( $provider_desc ) ) : ?>
|
169 |
+
<p class="desc"><?php echo $provider_desc; ?></p>
|
170 |
+
<?php endif; ?>
|
171 |
+
</div>
|
172 |
+
</div>
|
173 |
+
|
174 |
+
<?php $provider->display_options(); ?>
|
175 |
+
</div>
|
176 |
+
|
177 |
+
<?php endforeach; ?>
|
178 |
+
|
179 |
+
</div>
|
180 |
+
|
181 |
+
<p class="wp-mail-smtp-submit">
|
182 |
+
<button type="submit" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-orange"><?php esc_html_e( 'Save Settings', 'wp-mail-smtp' ); ?></button>
|
183 |
+
</p>
|
184 |
+
|
185 |
+
</form>
|
186 |
+
|
187 |
+
<?php
|
188 |
+
}
|
189 |
+
|
190 |
+
/**
|
191 |
+
* @inheritdoc
|
192 |
+
*/
|
193 |
+
public function process_post( $data ) {
|
194 |
+
|
195 |
+
$this->check_admin_referer();
|
196 |
+
|
197 |
+
$options = new Options();
|
198 |
+
$old_opt = $options->get_all();
|
199 |
+
|
200 |
+
$to_redirect = false;
|
201 |
+
|
202 |
+
// Old and new Gmail client id/secret values are different - we need to invalidate tokens and scroll to Auth button.
|
203 |
+
if (
|
204 |
+
$options->get( 'mail', 'mailer' ) === 'gmail' &&
|
205 |
+
(
|
206 |
+
$options->get( 'gmail', 'client_id' ) !== $data['gmail']['client_id'] ||
|
207 |
+
$options->get( 'gmail', 'client_secret' ) !== $data['gmail']['client_secret']
|
208 |
+
)
|
209 |
+
) {
|
210 |
+
unset( $old_opt['gmail'] );
|
211 |
+
|
212 |
+
if (
|
213 |
+
! empty( $data['gmail']['client_id'] ) &&
|
214 |
+
! empty( $data['gmail']['client_secret'] )
|
215 |
+
) {
|
216 |
+
$to_redirect = true;
|
217 |
+
}
|
218 |
+
}
|
219 |
+
|
220 |
+
// New gmail clients data will be added from new $data, except the old access/refresh_token.
|
221 |
+
$to_save = array_merge( $old_opt, $data );
|
222 |
+
|
223 |
+
// All the sanitization is done there.
|
224 |
+
$options->set( $to_save );
|
225 |
+
|
226 |
+
if ( $to_redirect ) {
|
227 |
+
wp_redirect( $_POST['_wp_http_referer'] . '#wp-mail-smtp-setting-row-gmail-authorize' );
|
228 |
+
exit;
|
229 |
+
}
|
230 |
+
|
231 |
+
WP::add_admin_notice(
|
232 |
+
esc_html__( 'Settings were successfully saved.', 'wp-mail-smtp' ),
|
233 |
+
WP::ADMIN_NOTICE_SUCCESS
|
234 |
+
);
|
235 |
+
}
|
236 |
+
}
|
src/Admin/Pages/Test.php
CHANGED
@@ -1,208 +1,235 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Admin\Pages;
|
4 |
-
|
5 |
-
use WPMailSMTP\MailCatcher;
|
6 |
-
use WPMailSMTP\Options;
|
7 |
-
use WPMailSMTP\WP;
|
8 |
-
use WPMailSMTP\Admin\PageAbstract;
|
9 |
-
|
10 |
-
/**
|
11 |
-
* Class Test is part of Area, displays email testing page of the plugin.
|
12 |
-
*
|
13 |
-
* @since 1.0.0
|
14 |
-
*/
|
15 |
-
class Test extends PageAbstract {
|
16 |
-
|
17 |
-
/**
|
18 |
-
* @var string Slug of a tab.
|
19 |
-
*/
|
20 |
-
protected $slug = 'test';
|
21 |
-
|
22 |
-
/**
|
23 |
-
* @inheritdoc
|
24 |
-
*/
|
25 |
-
public function get_label() {
|
26 |
-
return esc_html__( 'Email Test', 'wp-mail-smtp' );
|
27 |
-
}
|
28 |
-
|
29 |
-
/**
|
30 |
-
* @inheritdoc
|
31 |
-
*/
|
32 |
-
public function get_title() {
|
33 |
-
return $this->get_label();
|
34 |
-
}
|
35 |
-
|
36 |
-
/**
|
37 |
-
* @inheritdoc
|
38 |
-
*/
|
39 |
-
public function display() {
|
40 |
-
?>
|
41 |
-
|
42 |
-
<form method="POST" action="">
|
43 |
-
<?php $this->wp_nonce_field(); ?>
|
44 |
-
|
45 |
-
<!-- Test Email Section Title -->
|
46 |
-
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading no-desc" id="wp-mail-smtp-setting-row-email-heading">
|
47 |
-
<div class="wp-mail-smtp-setting-field">
|
48 |
-
<h2><?php esc_html_e( 'Send a Test Email', 'wp-mail-smtp' ); ?></h2>
|
49 |
-
</div>
|
50 |
-
</div>
|
51 |
-
|
52 |
-
<!-- Test Email -->
|
53 |
-
<div id="wp-mail-smtp-setting-row-test_email" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-email wp-mail-smtp-clear">
|
54 |
-
<div class="wp-mail-smtp-setting-label">
|
55 |
-
<label for="wp-mail-smtp-setting-test_email"><?php esc_html_e( 'Send To', 'wp-mail-smtp' ); ?></label>
|
56 |
-
</div>
|
57 |
-
<div class="wp-mail-smtp-setting-field">
|
58 |
-
<input name="wp-mail-smtp[test_email]" type="email" id="wp-mail-smtp-setting-test_email" spellcheck="false" required />
|
59 |
-
<p class="desc">
|
60 |
-
<?php esc_html_e( 'Type an email address here and then click a button below to generate a test email.', 'wp-mail-smtp' ); ?>
|
61 |
-
</p>
|
62 |
-
</div>
|
63 |
-
</div>
|
64 |
-
|
65 |
-
<p class="wp-mail-smtp-submit">
|
66 |
-
<button type="submit" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-orange"><?php esc_html_e( 'Send Email', 'wp-mail-smtp' ); ?></button>
|
67 |
-
</p>
|
68 |
-
</form>
|
69 |
-
|
70 |
-
<?php
|
71 |
-
}
|
72 |
-
|
73 |
-
/**
|
74 |
-
* @inheritdoc
|
75 |
-
*/
|
76 |
-
public function process_post( $data ) {
|
77 |
-
|
78 |
-
$this->check_admin_referer();
|
79 |
-
|
80 |
-
if ( isset( $data['test_email'] ) ) {
|
81 |
-
$data['test_email'] = filter_var( $data['test_email'], FILTER_VALIDATE_EMAIL );
|
82 |
-
}
|
83 |
-
|
84 |
-
if ( empty( $data['test_email'] ) ) {
|
85 |
-
WP::add_admin_notice(
|
86 |
-
esc_html__( 'Test failed. Please use a valid email address and try to resend the test email.', 'wp-mail-smtp' ),
|
87 |
-
WP::ADMIN_NOTICE_WARNING
|
88 |
-
);
|
89 |
-
return;
|
90 |
-
}
|
91 |
-
|
92 |
-
global $phpmailer;
|
93 |
-
|
94 |
-
// Make sure the PHPMailer class has been instantiated.
|
95 |
-
if ( ! is_object( $phpmailer ) || ! is_a( $phpmailer, 'PHPMailer' ) ) {
|
96 |
-
require_once ABSPATH . WPINC . '/class-phpmailer.php';
|
97 |
-
$phpmailer = new MailCatcher( true );
|
98 |
-
}
|
99 |
-
|
100 |
-
// Set SMTPDebug level, default is
|
101 |
-
$phpmailer->SMTPDebug = apply_filters( 'wp_mail_smtp_admin_test_email_smtp_debug',
|
102 |
-
|
103 |
-
// Start output buffering to grab smtp debugging output.
|
104 |
-
ob_start();
|
105 |
-
|
106 |
-
// Send the test mail.
|
107 |
-
$result = wp_mail(
|
108 |
-
$data['test_email'],
|
109 |
-
/* translators: %s - email address a test email will be sent to. */
|
110 |
-
'WP Mail SMTP: ' . sprintf( esc_html__( 'Test email to %s', 'wp-mail-smtp' ), $data['test_email'] ),
|
111 |
-
sprintf(
|
112 |
-
/* translators: %s - mailer name. */
|
113 |
-
esc_html__( 'This email was sent by %s mailer, and generated by the WP Mail SMTP WordPress plugin.', 'wp-mail-smtp' ),
|
114 |
-
wp_mail_smtp()->get_providers()->get_options( Options::init()->get( 'mail', 'mailer' ) )->get_title()
|
115 |
-
)
|
116 |
-
);
|
117 |
-
|
118 |
-
// Grab the smtp debugging output.
|
119 |
-
$smtp_debug = ob_get_clean();
|
120 |
-
|
121 |
-
/*
|
122 |
-
* Do the actual sending.
|
123 |
-
*/
|
124 |
-
if ( $result ) {
|
125 |
-
WP::add_admin_notice(
|
126 |
-
esc_html__( 'Your email was sent successfully!', 'wp-mail-smtp' ),
|
127 |
-
WP::ADMIN_NOTICE_SUCCESS
|
128 |
-
);
|
129 |
-
} else {
|
130 |
-
$error = $this->get_debug_messages( $phpmailer, $smtp_debug );
|
131 |
-
|
132 |
-
WP::add_admin_notice(
|
133 |
-
'<p><strong>' . esc_html__( 'There was a problem while sending a test email.', 'wp-mail-smtp' ) . '</strong></p>' .
|
134 |
-
'<p>' . esc_html__( 'The related debugging output is shown below:', 'wp-mail-smtp' ) . '</p>' .
|
135 |
-
'<blockquote>' . $error . '</blockquote>'
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
*
|
144 |
-
*
|
145 |
-
* @
|
146 |
-
*
|
147 |
-
* @
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
$
|
164 |
-
|
165 |
-
$
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
$
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
$
|
177 |
-
|
178 |
-
|
179 |
-
$
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Admin\Pages;
|
4 |
+
|
5 |
+
use WPMailSMTP\MailCatcher;
|
6 |
+
use WPMailSMTP\Options;
|
7 |
+
use WPMailSMTP\WP;
|
8 |
+
use WPMailSMTP\Admin\PageAbstract;
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Class Test is part of Area, displays email testing page of the plugin.
|
12 |
+
*
|
13 |
+
* @since 1.0.0
|
14 |
+
*/
|
15 |
+
class Test extends PageAbstract {
|
16 |
+
|
17 |
+
/**
|
18 |
+
* @var string Slug of a tab.
|
19 |
+
*/
|
20 |
+
protected $slug = 'test';
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @inheritdoc
|
24 |
+
*/
|
25 |
+
public function get_label() {
|
26 |
+
return esc_html__( 'Email Test', 'wp-mail-smtp' );
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @inheritdoc
|
31 |
+
*/
|
32 |
+
public function get_title() {
|
33 |
+
return $this->get_label();
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* @inheritdoc
|
38 |
+
*/
|
39 |
+
public function display() {
|
40 |
+
?>
|
41 |
+
|
42 |
+
<form method="POST" action="">
|
43 |
+
<?php $this->wp_nonce_field(); ?>
|
44 |
+
|
45 |
+
<!-- Test Email Section Title -->
|
46 |
+
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading no-desc" id="wp-mail-smtp-setting-row-email-heading">
|
47 |
+
<div class="wp-mail-smtp-setting-field">
|
48 |
+
<h2><?php esc_html_e( 'Send a Test Email', 'wp-mail-smtp' ); ?></h2>
|
49 |
+
</div>
|
50 |
+
</div>
|
51 |
+
|
52 |
+
<!-- Test Email -->
|
53 |
+
<div id="wp-mail-smtp-setting-row-test_email" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-email wp-mail-smtp-clear">
|
54 |
+
<div class="wp-mail-smtp-setting-label">
|
55 |
+
<label for="wp-mail-smtp-setting-test_email"><?php esc_html_e( 'Send To', 'wp-mail-smtp' ); ?></label>
|
56 |
+
</div>
|
57 |
+
<div class="wp-mail-smtp-setting-field">
|
58 |
+
<input name="wp-mail-smtp[test_email]" type="email" id="wp-mail-smtp-setting-test_email" spellcheck="false" required />
|
59 |
+
<p class="desc">
|
60 |
+
<?php esc_html_e( 'Type an email address here and then click a button below to generate a test email.', 'wp-mail-smtp' ); ?>
|
61 |
+
</p>
|
62 |
+
</div>
|
63 |
+
</div>
|
64 |
+
|
65 |
+
<p class="wp-mail-smtp-submit">
|
66 |
+
<button type="submit" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-orange"><?php esc_html_e( 'Send Email', 'wp-mail-smtp' ); ?></button>
|
67 |
+
</p>
|
68 |
+
</form>
|
69 |
+
|
70 |
+
<?php
|
71 |
+
}
|
72 |
+
|
73 |
+
/**
|
74 |
+
* @inheritdoc
|
75 |
+
*/
|
76 |
+
public function process_post( $data ) {
|
77 |
+
|
78 |
+
$this->check_admin_referer();
|
79 |
+
|
80 |
+
if ( isset( $data['test_email'] ) ) {
|
81 |
+
$data['test_email'] = filter_var( $data['test_email'], FILTER_VALIDATE_EMAIL );
|
82 |
+
}
|
83 |
+
|
84 |
+
if ( empty( $data['test_email'] ) ) {
|
85 |
+
WP::add_admin_notice(
|
86 |
+
esc_html__( 'Test failed. Please use a valid email address and try to resend the test email.', 'wp-mail-smtp' ),
|
87 |
+
WP::ADMIN_NOTICE_WARNING
|
88 |
+
);
|
89 |
+
return;
|
90 |
+
}
|
91 |
+
|
92 |
+
global $phpmailer;
|
93 |
+
|
94 |
+
// Make sure the PHPMailer class has been instantiated.
|
95 |
+
if ( ! is_object( $phpmailer ) || ! is_a( $phpmailer, 'PHPMailer' ) ) {
|
96 |
+
require_once ABSPATH . WPINC . '/class-phpmailer.php';
|
97 |
+
$phpmailer = new MailCatcher( true );
|
98 |
+
}
|
99 |
+
|
100 |
+
// Set SMTPDebug level, default is 3 (commands + data + connection status).
|
101 |
+
$phpmailer->SMTPDebug = apply_filters( 'wp_mail_smtp_admin_test_email_smtp_debug', 3 );
|
102 |
+
|
103 |
+
// Start output buffering to grab smtp debugging output.
|
104 |
+
ob_start();
|
105 |
+
|
106 |
+
// Send the test mail.
|
107 |
+
$result = wp_mail(
|
108 |
+
$data['test_email'],
|
109 |
+
/* translators: %s - email address a test email will be sent to. */
|
110 |
+
'WP Mail SMTP: ' . sprintf( esc_html__( 'Test email to %s', 'wp-mail-smtp' ), $data['test_email'] ),
|
111 |
+
sprintf(
|
112 |
+
/* translators: %s - mailer name. */
|
113 |
+
esc_html__( 'This email was sent by %s mailer, and generated by the WP Mail SMTP WordPress plugin.', 'wp-mail-smtp' ),
|
114 |
+
wp_mail_smtp()->get_providers()->get_options( Options::init()->get( 'mail', 'mailer' ) )->get_title()
|
115 |
+
)
|
116 |
+
);
|
117 |
+
|
118 |
+
// Grab the smtp debugging output.
|
119 |
+
$smtp_debug = ob_get_clean();
|
120 |
+
|
121 |
+
/*
|
122 |
+
* Do the actual sending.
|
123 |
+
*/
|
124 |
+
if ( $result ) {
|
125 |
+
WP::add_admin_notice(
|
126 |
+
esc_html__( 'Your email was sent successfully!', 'wp-mail-smtp' ),
|
127 |
+
WP::ADMIN_NOTICE_SUCCESS
|
128 |
+
);
|
129 |
+
} else {
|
130 |
+
$error = $this->get_debug_messages( $phpmailer, $smtp_debug );
|
131 |
+
|
132 |
+
WP::add_admin_notice(
|
133 |
+
'<p><strong>' . esc_html__( 'There was a problem while sending a test email.', 'wp-mail-smtp' ) . '</strong></p>' .
|
134 |
+
'<p>' . esc_html__( 'The related debugging output is shown below:', 'wp-mail-smtp' ) . '</p>' .
|
135 |
+
'<blockquote style="border-left:1px solid orange;padding-left:10px">' . $error . '</blockquote>' .
|
136 |
+
'<p class="description">' . esc_html__( 'Please copy only the content of the error debug message above, identified with an orange left border, into the support forum topic if you experience any issues.', 'wp-mail-smtp' ) . '</p>',
|
137 |
+
WP::ADMIN_NOTICE_ERROR
|
138 |
+
);
|
139 |
+
}
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Prepare debug information, that will help users to identify the error.
|
144 |
+
*
|
145 |
+
* @since 1.0.0
|
146 |
+
*
|
147 |
+
* @param \PHPMailer $phpmailer
|
148 |
+
* @param string $smtp_debug
|
149 |
+
*
|
150 |
+
* @return string
|
151 |
+
*/
|
152 |
+
protected function get_debug_messages( $phpmailer, $smtp_debug ) {
|
153 |
+
|
154 |
+
$options = new Options();
|
155 |
+
|
156 |
+
/*
|
157 |
+
* Versions Debug.
|
158 |
+
*/
|
159 |
+
|
160 |
+
$versions_text = '<strong>Versions:</strong><br>';
|
161 |
+
|
162 |
+
$versions_text .= '<strong>WordPress:</strong> ' . get_bloginfo( 'version' ) . '<br>';
|
163 |
+
$versions_text .= '<strong>WordPress MS:</strong> ' . ( is_multisite() ? 'Yes' : 'No' ) . '<br>';
|
164 |
+
$versions_text .= '<strong>PHP:</strong> ' . PHP_VERSION . '<br>';
|
165 |
+
$versions_text .= '<strong>WP Mail SMTP:</strong> ' . WPMS_PLUGIN_VER . '<br>';
|
166 |
+
|
167 |
+
/*
|
168 |
+
* Mailer Debug.
|
169 |
+
*/
|
170 |
+
|
171 |
+
$mailer_text = '<strong>PHPMailer:</strong><br>';
|
172 |
+
|
173 |
+
$mailer_text .= '<strong>Mailer:</strong> ' . $phpmailer->Mailer . '<br>';
|
174 |
+
|
175 |
+
// Display different debug info based on the mailer.
|
176 |
+
if ( $options->is_mailer_smtp() ) {
|
177 |
+
$mailer_text .= '<strong>ErrorInfo:</strong> ' . make_clickable( $phpmailer->ErrorInfo ) . '<br>';
|
178 |
+
$mailer_text .= '<strong>Host:</strong> ' . $phpmailer->Host . '<br>';
|
179 |
+
$mailer_text .= '<strong>Port:</strong> ' . $phpmailer->Port . '<br>';
|
180 |
+
$mailer_text .= '<strong>SMTPSecure:</strong> ' . $this->pvar( $phpmailer->SMTPSecure ) . '<br>';
|
181 |
+
$mailer_text .= '<strong>SMTPAutoTLS:</strong> ' . $this->pvar( $phpmailer->SMTPAutoTLS ) . '<br>';
|
182 |
+
$mailer_text .= '<strong>SMTPAuth:</strong> ' . $this->pvar( $phpmailer->SMTPAuth );
|
183 |
+
if ( ! empty( $phpmailer->SMTPOptions ) ) {
|
184 |
+
$mailer_text .= '<br><strong>SMTPOptions:</strong> <code>' . json_encode( $phpmailer->SMTPOptions ) . '</code>';
|
185 |
+
}
|
186 |
+
}
|
187 |
+
|
188 |
+
/*
|
189 |
+
* SMTP Debug.
|
190 |
+
*/
|
191 |
+
|
192 |
+
$smtp_text = '<br><strong>SMTP Debug:</strong><br>';
|
193 |
+
if ( ! empty( $smtp_debug ) ) {
|
194 |
+
$smtp_text .= $smtp_debug;
|
195 |
+
} else {
|
196 |
+
$smtp_text .= '[empty]';
|
197 |
+
}
|
198 |
+
|
199 |
+
$errors = apply_filters( 'wp_mail_smtp_admin_test_get_debug_messages', array(
|
200 |
+
$versions_text,
|
201 |
+
$mailer_text,
|
202 |
+
$smtp_text,
|
203 |
+
) );
|
204 |
+
|
205 |
+
return '<pre>' . implode( '<br>', $errors ) . '</pre>';
|
206 |
+
}
|
207 |
+
|
208 |
+
/**
|
209 |
+
* Get the proper variable content output to debug.
|
210 |
+
*
|
211 |
+
* @since 1.0.0
|
212 |
+
*
|
213 |
+
* @param mixed $var
|
214 |
+
*
|
215 |
+
* @return string
|
216 |
+
*/
|
217 |
+
protected function pvar( $var = '' ) {
|
218 |
+
|
219 |
+
ob_start();
|
220 |
+
|
221 |
+
echo '<code>';
|
222 |
+
|
223 |
+
if ( is_bool( $var ) || empty( $var ) ) {
|
224 |
+
var_dump( $var );
|
225 |
+
} else {
|
226 |
+
print_r( $var );
|
227 |
+
}
|
228 |
+
|
229 |
+
echo '</code>';
|
230 |
+
|
231 |
+
$output = ob_get_clean();
|
232 |
+
|
233 |
+
return str_replace( array( "\r\n", "\r", "\n" ), '', $output );
|
234 |
+
}
|
235 |
+
}
|
src/Core.php
CHANGED
@@ -1,213 +1,239 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Class Core to handle all plugin initialization.
|
7 |
-
*
|
8 |
-
* @since 1.0.0
|
9 |
-
*/
|
10 |
-
class Core {
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Without trailing slash.
|
14 |
-
*
|
15 |
-
* @var string
|
16 |
-
*/
|
17 |
-
public $plugin_url;
|
18 |
-
/**
|
19 |
-
* Without trailing slash.
|
20 |
-
*
|
21 |
-
* @var string
|
22 |
-
*/
|
23 |
-
public $plugin_path;
|
24 |
-
|
25 |
-
/**
|
26 |
-
* Core constructor.
|
27 |
-
*
|
28 |
-
* @since 1.0.0
|
29 |
-
*/
|
30 |
-
public function __construct() {
|
31 |
-
|
32 |
-
$this->plugin_url = rtrim( plugin_dir_url( __DIR__ ), '/\\' );
|
33 |
-
$this->plugin_path = rtrim( plugin_dir_path( __DIR__ ), '/\\' );
|
34 |
-
|
35 |
-
$this->hooks();
|
36 |
-
}
|
37 |
-
|
38 |
-
/**
|
39 |
-
* Assign all hooks to proper places.
|
40 |
-
*
|
41 |
-
* @since 1.0.0
|
42 |
-
*/
|
43 |
-
public function hooks() {
|
44 |
-
|
45 |
-
// Activation hook.
|
46 |
-
add_action( 'activate_wp-mail-smtp/wp_mail_smtp.php', array( $this, 'activate' ) );
|
47 |
-
|
48 |
-
add_action( 'plugins_loaded', array( $this, 'get_processor' ) );
|
49 |
-
add_action( 'plugins_loaded', array( $this, 'replace_phpmailer' ) );
|
50 |
-
add_action( 'plugins_loaded', array( $this, 'init_notifications' ) );
|
51 |
-
|
52 |
-
add_action( 'admin_notices', array( '\WPMailSMTP\WP', 'display_admin_notices' ) );
|
53 |
-
|
54 |
-
add_action( 'init', array( $this, 'init' ) );
|
55 |
-
}
|
56 |
-
|
57 |
-
/**
|
58 |
-
* Initial plugin actions.
|
59 |
-
*
|
60 |
-
* @since 1.0.0
|
61 |
-
*/
|
62 |
-
public function init() {
|
63 |
-
|
64 |
-
// Load translations just in case.
|
65 |
-
load_plugin_textdomain( 'wp-mail-smtp', false, wp_mail_smtp()->plugin_path . '/languages' );
|
66 |
-
|
67 |
-
/*
|
68 |
-
* Constantly check in admin area, that we don't need to upgrade DB.
|
69 |
-
* Do not wait for the `admin_init` hook, because some actions are already done
|
70 |
-
* on `plugins_loaded`, so migration has to be done before.
|
71 |
-
*/
|
72 |
-
if ( WP::in_wp_admin() ) {
|
73 |
-
$this->get_migration();
|
74 |
-
$this->
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
*
|
81 |
-
*
|
82 |
-
*
|
83 |
-
*
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
*
|
99 |
-
*
|
100 |
-
*
|
101 |
-
*
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
*
|
117 |
-
*
|
118 |
-
*
|
119 |
-
*
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
*
|
135 |
-
*
|
136 |
-
*
|
137 |
-
*
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
*
|
153 |
-
*
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
*
|
171 |
-
*
|
172 |
-
*
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
*
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Class Core to handle all plugin initialization.
|
7 |
+
*
|
8 |
+
* @since 1.0.0
|
9 |
+
*/
|
10 |
+
class Core {
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Without trailing slash.
|
14 |
+
*
|
15 |
+
* @var string
|
16 |
+
*/
|
17 |
+
public $plugin_url;
|
18 |
+
/**
|
19 |
+
* Without trailing slash.
|
20 |
+
*
|
21 |
+
* @var string
|
22 |
+
*/
|
23 |
+
public $plugin_path;
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Core constructor.
|
27 |
+
*
|
28 |
+
* @since 1.0.0
|
29 |
+
*/
|
30 |
+
public function __construct() {
|
31 |
+
|
32 |
+
$this->plugin_url = rtrim( plugin_dir_url( __DIR__ ), '/\\' );
|
33 |
+
$this->plugin_path = rtrim( plugin_dir_path( __DIR__ ), '/\\' );
|
34 |
+
|
35 |
+
$this->hooks();
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Assign all hooks to proper places.
|
40 |
+
*
|
41 |
+
* @since 1.0.0
|
42 |
+
*/
|
43 |
+
public function hooks() {
|
44 |
+
|
45 |
+
// Activation hook.
|
46 |
+
add_action( 'activate_wp-mail-smtp/wp_mail_smtp.php', array( $this, 'activate' ) );
|
47 |
+
|
48 |
+
add_action( 'plugins_loaded', array( $this, 'get_processor' ) );
|
49 |
+
add_action( 'plugins_loaded', array( $this, 'replace_phpmailer' ) );
|
50 |
+
add_action( 'plugins_loaded', array( $this, 'init_notifications' ) );
|
51 |
+
|
52 |
+
add_action( 'admin_notices', array( '\WPMailSMTP\WP', 'display_admin_notices' ) );
|
53 |
+
|
54 |
+
add_action( 'init', array( $this, 'init' ) );
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Initial plugin actions.
|
59 |
+
*
|
60 |
+
* @since 1.0.0
|
61 |
+
*/
|
62 |
+
public function init() {
|
63 |
+
|
64 |
+
// Load translations just in case.
|
65 |
+
load_plugin_textdomain( 'wp-mail-smtp', false, wp_mail_smtp()->plugin_path . '/languages' );
|
66 |
+
|
67 |
+
/*
|
68 |
+
* Constantly check in admin area, that we don't need to upgrade DB.
|
69 |
+
* Do not wait for the `admin_init` hook, because some actions are already done
|
70 |
+
* on `plugins_loaded`, so migration has to be done before.
|
71 |
+
*/
|
72 |
+
if ( WP::in_wp_admin() ) {
|
73 |
+
$this->get_migration();
|
74 |
+
$this->get_upgrade();
|
75 |
+
$this->get_admin();
|
76 |
+
}
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Load the plugin core processor.
|
81 |
+
*
|
82 |
+
* @since 1.0.0
|
83 |
+
*
|
84 |
+
* @return Processor
|
85 |
+
*/
|
86 |
+
public function get_processor() {
|
87 |
+
|
88 |
+
static $processor;
|
89 |
+
|
90 |
+
if ( ! isset( $processor ) ) {
|
91 |
+
$processor = apply_filters( 'wp_mail_smtp_core_get_processor', new Processor() );
|
92 |
+
}
|
93 |
+
|
94 |
+
return $processor;
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Load the plugin admin area.
|
99 |
+
*
|
100 |
+
* @since 1.0.0
|
101 |
+
*
|
102 |
+
* @return Admin\Area
|
103 |
+
*/
|
104 |
+
public function get_admin() {
|
105 |
+
|
106 |
+
static $admin;
|
107 |
+
|
108 |
+
if ( ! isset( $admin ) ) {
|
109 |
+
$admin = apply_filters( 'wp_mail_smtp_core_get_admin', new Admin\Area() );
|
110 |
+
}
|
111 |
+
|
112 |
+
return $admin;
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Load the plugin providers loader.
|
117 |
+
*
|
118 |
+
* @since 1.0.0
|
119 |
+
*
|
120 |
+
* @return Providers\Loader
|
121 |
+
*/
|
122 |
+
public function get_providers() {
|
123 |
+
|
124 |
+
static $providers;
|
125 |
+
|
126 |
+
if ( ! isset( $providers ) ) {
|
127 |
+
$providers = apply_filters( 'wp_mail_smtp_core_get_providers', new Providers\Loader() );
|
128 |
+
}
|
129 |
+
|
130 |
+
return $providers;
|
131 |
+
}
|
132 |
+
|
133 |
+
/**
|
134 |
+
* Load the plugin option migrator.
|
135 |
+
*
|
136 |
+
* @since 1.0.0
|
137 |
+
*
|
138 |
+
* @return Migration
|
139 |
+
*/
|
140 |
+
public function get_migration() {
|
141 |
+
|
142 |
+
static $migration;
|
143 |
+
|
144 |
+
if ( ! isset( $migration ) ) {
|
145 |
+
$migration = apply_filters( 'wp_mail_smtp_core_get_migration', new Migration() );
|
146 |
+
}
|
147 |
+
|
148 |
+
return $migration;
|
149 |
+
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Load the plugin upgrader.
|
153 |
+
*
|
154 |
+
* @since 1.1.0
|
155 |
+
*
|
156 |
+
* @return Upgrade
|
157 |
+
*/
|
158 |
+
public function get_upgrade() {
|
159 |
+
|
160 |
+
static $upgrade;
|
161 |
+
|
162 |
+
if ( ! isset( $upgrade ) ) {
|
163 |
+
$upgrade = apply_filters( 'wp_mail_smtp_core_get_upgrade', new Upgrade() );
|
164 |
+
}
|
165 |
+
|
166 |
+
return $upgrade;
|
167 |
+
}
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Awesome Motive Notifications.
|
171 |
+
*
|
172 |
+
* @since 1.0.0
|
173 |
+
*/
|
174 |
+
public function init_notifications() {
|
175 |
+
|
176 |
+
if ( Options::init()->get( 'general', 'am_notifications_hidden' ) ) {
|
177 |
+
return;
|
178 |
+
}
|
179 |
+
|
180 |
+
static $notification;
|
181 |
+
|
182 |
+
if ( ! isset( $notification ) ) {
|
183 |
+
$notification = new AM_Notification( 'smtp', WPMS_PLUGIN_VER );
|
184 |
+
}
|
185 |
+
}
|
186 |
+
|
187 |
+
/**
|
188 |
+
* Init the \PHPMailer replacement.
|
189 |
+
*
|
190 |
+
* @since 1.0.0
|
191 |
+
*
|
192 |
+
* @return \WPMailSMTP\MailCatcher
|
193 |
+
*/
|
194 |
+
public function replace_phpmailer() {
|
195 |
+
global $phpmailer;
|
196 |
+
|
197 |
+
return $this->replace_w_fake_phpmailer( $phpmailer );
|
198 |
+
}
|
199 |
+
|
200 |
+
/**
|
201 |
+
* Overwrite default PhpMailer with out MailCatcher.
|
202 |
+
*
|
203 |
+
* @since 1.0.0
|
204 |
+
*
|
205 |
+
* @param null $obj
|
206 |
+
*
|
207 |
+
* @return \WPMailSMTP\MailCatcher
|
208 |
+
*/
|
209 |
+
protected function replace_w_fake_phpmailer( &$obj = null ) {
|
210 |
+
|
211 |
+
$obj = new MailCatcher();
|
212 |
+
|
213 |
+
return $obj;
|
214 |
+
}
|
215 |
+
|
216 |
+
/**
|
217 |
+
* What to do on plugin activation.
|
218 |
+
*
|
219 |
+
* @since 1.0.0
|
220 |
+
*/
|
221 |
+
public function activate() {
|
222 |
+
|
223 |
+
// Store the plugin version activated to reference with upgrades.
|
224 |
+
update_option( 'wp_mail_smtp_version', WPMS_PLUGIN_VER );
|
225 |
+
|
226 |
+
// Create and store inital plugin settings.
|
227 |
+
$options['mail'] = array(
|
228 |
+
'from_email' => get_option( 'admin_email' ),
|
229 |
+
'from_name' => get_bloginfo( 'name' ),
|
230 |
+
'mailer' => 'mail',
|
231 |
+
'return_path' => false,
|
232 |
+
'smtp' => array(
|
233 |
+
'autotls' => true,
|
234 |
+
),
|
235 |
+
);
|
236 |
+
|
237 |
+
Options::init()->set( $options );
|
238 |
+
}
|
239 |
+
}
|
src/MailCatcher.php
CHANGED
@@ -1,66 +1,66 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP;
|
4 |
-
|
5 |
-
// Load PHPMailer class, so we can subclass it.
|
6 |
-
if ( ! class_exists( 'PHPMailer', false ) ) {
|
7 |
-
require_once ABSPATH . WPINC . '/class-phpmailer.php';
|
8 |
-
}
|
9 |
-
|
10 |
-
/**
|
11 |
-
* Class MailCatcher replaces the \PHPMailer and modifies the email sending logic.
|
12 |
-
* Thus, we can use other mailers API to do what we need, or stop emails completely.
|
13 |
-
*
|
14 |
-
* @since 1.0.0
|
15 |
-
*/
|
16 |
-
class MailCatcher extends \PHPMailer {
|
17 |
-
|
18 |
-
/**
|
19 |
-
* Modify the default send() behaviour.
|
20 |
-
* For those mailers, that relies on PHPMailer class - call it directly.
|
21 |
-
* For others - init the correct provider and process it.
|
22 |
-
*
|
23 |
-
* @since 1.0.0
|
24 |
-
*
|
25 |
-
* @throws \phpmailerException Throws when sending via PhpMailer fails for some reason.
|
26 |
-
*
|
27 |
-
* @return bool
|
28 |
-
*/
|
29 |
-
public function send() {
|
30 |
-
|
31 |
-
$options = new Options();
|
32 |
-
$mailer = $options->get( 'mail', 'mailer' );
|
33 |
-
|
34 |
-
// Use the default PHPMailer, as we inject our settings there for certain providers.
|
35 |
-
if (
|
36 |
-
$mailer === 'mail' ||
|
37 |
-
$mailer === 'smtp' ||
|
38 |
-
$mailer === 'pepipost'
|
39 |
-
) {
|
40 |
-
return parent::send();
|
41 |
-
}
|
42 |
-
|
43 |
-
// Prepare everything (including the message) for sending.
|
44 |
-
if ( ! $this->preSend() ) {
|
45 |
-
return false;
|
46 |
-
}
|
47 |
-
|
48 |
-
$mailer = wp_mail_smtp()->get_providers()->get_mailer( $mailer, $this );
|
49 |
-
|
50 |
-
if ( ! $mailer ) {
|
51 |
-
return false;
|
52 |
-
}
|
53 |
-
|
54 |
-
if ( ! $mailer->is_php_compatible() ) {
|
55 |
-
return false;
|
56 |
-
}
|
57 |
-
|
58 |
-
/*
|
59 |
-
* Send the actual email.
|
60 |
-
* We reuse everything, that was preprocessed for usage in \PHPMailer.
|
61 |
-
*/
|
62 |
-
$mailer->send();
|
63 |
-
|
64 |
-
return $mailer->is_email_sent();
|
65 |
-
}
|
66 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP;
|
4 |
+
|
5 |
+
// Load PHPMailer class, so we can subclass it.
|
6 |
+
if ( ! class_exists( 'PHPMailer', false ) ) {
|
7 |
+
require_once ABSPATH . WPINC . '/class-phpmailer.php';
|
8 |
+
}
|
9 |
+
|
10 |
+
/**
|
11 |
+
* Class MailCatcher replaces the \PHPMailer and modifies the email sending logic.
|
12 |
+
* Thus, we can use other mailers API to do what we need, or stop emails completely.
|
13 |
+
*
|
14 |
+
* @since 1.0.0
|
15 |
+
*/
|
16 |
+
class MailCatcher extends \PHPMailer {
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Modify the default send() behaviour.
|
20 |
+
* For those mailers, that relies on PHPMailer class - call it directly.
|
21 |
+
* For others - init the correct provider and process it.
|
22 |
+
*
|
23 |
+
* @since 1.0.0
|
24 |
+
*
|
25 |
+
* @throws \phpmailerException Throws when sending via PhpMailer fails for some reason.
|
26 |
+
*
|
27 |
+
* @return bool
|
28 |
+
*/
|
29 |
+
public function send() {
|
30 |
+
|
31 |
+
$options = new Options();
|
32 |
+
$mailer = $options->get( 'mail', 'mailer' );
|
33 |
+
|
34 |
+
// Use the default PHPMailer, as we inject our settings there for certain providers.
|
35 |
+
if (
|
36 |
+
$mailer === 'mail' ||
|
37 |
+
$mailer === 'smtp' ||
|
38 |
+
$mailer === 'pepipost'
|
39 |
+
) {
|
40 |
+
return parent::send();
|
41 |
+
}
|
42 |
+
|
43 |
+
// Prepare everything (including the message) for sending.
|
44 |
+
if ( ! $this->preSend() ) {
|
45 |
+
return false;
|
46 |
+
}
|
47 |
+
|
48 |
+
$mailer = wp_mail_smtp()->get_providers()->get_mailer( $mailer, $this );
|
49 |
+
|
50 |
+
if ( ! $mailer ) {
|
51 |
+
return false;
|
52 |
+
}
|
53 |
+
|
54 |
+
if ( ! $mailer->is_php_compatible() ) {
|
55 |
+
return false;
|
56 |
+
}
|
57 |
+
|
58 |
+
/*
|
59 |
+
* Send the actual email.
|
60 |
+
* We reuse everything, that was preprocessed for usage in \PHPMailer.
|
61 |
+
*/
|
62 |
+
$mailer->send();
|
63 |
+
|
64 |
+
return $mailer->is_email_sent();
|
65 |
+
}
|
66 |
+
}
|
src/Migration.php
CHANGED
@@ -1,245 +1,245 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Class Migration helps migrate all plugin options saved into DB to a new storage location.
|
7 |
-
*
|
8 |
-
* @since 1.0.0
|
9 |
-
*/
|
10 |
-
class Migration {
|
11 |
-
|
12 |
-
/**
|
13 |
-
* All old values for pre 1.0 version of a plugin.
|
14 |
-
*
|
15 |
-
* @var array
|
16 |
-
*/
|
17 |
-
protected $old_keys = array(
|
18 |
-
'pepipost_ssl',
|
19 |
-
'pepipost_port',
|
20 |
-
'pepipost_pass',
|
21 |
-
'pepipost_user',
|
22 |
-
'smtp_pass',
|
23 |
-
'smtp_user',
|
24 |
-
'smtp_auth',
|
25 |
-
'smtp_ssl',
|
26 |
-
'smtp_port',
|
27 |
-
'smtp_host',
|
28 |
-
'mail_set_return_path',
|
29 |
-
'mailer',
|
30 |
-
'mail_from_name',
|
31 |
-
'mail_from',
|
32 |
-
'wp_mail_smtp_am_notifications_hidden',
|
33 |
-
);
|
34 |
-
|
35 |
-
/**
|
36 |
-
* Old values, taken from $old_keys options.
|
37 |
-
*
|
38 |
-
* @var array
|
39 |
-
*/
|
40 |
-
protected $old_values = array();
|
41 |
-
|
42 |
-
/**
|
43 |
-
* Converted array of data from previous option values.
|
44 |
-
*
|
45 |
-
* @var array
|
46 |
-
*/
|
47 |
-
protected $new_values = array();
|
48 |
-
|
49 |
-
/**
|
50 |
-
* Migration constructor.
|
51 |
-
*
|
52 |
-
* @since 1.0.0
|
53 |
-
*/
|
54 |
-
public function __construct() {
|
55 |
-
|
56 |
-
if ( $this->is_migrated() ) {
|
57 |
-
return;
|
58 |
-
}
|
59 |
-
|
60 |
-
$this->old_values = $this->get_old_values();
|
61 |
-
$this->new_values = $this->get_converted_options();
|
62 |
-
|
63 |
-
Options::init()->set( $this->new_values );
|
64 |
-
|
65 |
-
// Removing all options will be enabled some time in the future.
|
66 |
-
// $this->clean_deprecated_data();
|
67 |
-
}
|
68 |
-
|
69 |
-
/**
|
70 |
-
* Whether we already migrated or not.
|
71 |
-
*
|
72 |
-
* @since 1.0.0
|
73 |
-
*
|
74 |
-
* @return bool
|
75 |
-
*/
|
76 |
-
protected function is_migrated() {
|
77 |
-
|
78 |
-
$is_migrated = false;
|
79 |
-
$new_values = get_option( Options::META_KEY, array() );
|
80 |
-
|
81 |
-
if ( ! empty( $new_values ) ) {
|
82 |
-
$is_migrated = true;
|
83 |
-
}
|
84 |
-
|
85 |
-
return $is_migrated;
|
86 |
-
}
|
87 |
-
|
88 |
-
/**
|
89 |
-
* Get all old values from DB.
|
90 |
-
*
|
91 |
-
* @since 1.0.0
|
92 |
-
*
|
93 |
-
* @return array
|
94 |
-
*/
|
95 |
-
protected function get_old_values() {
|
96 |
-
|
97 |
-
$old_values = array();
|
98 |
-
|
99 |
-
foreach ( $this->old_keys as $old_key ) {
|
100 |
-
$old_values[ $old_key ] = get_option( $old_key, '' );
|
101 |
-
}
|
102 |
-
|
103 |
-
return $old_values;
|
104 |
-
}
|
105 |
-
|
106 |
-
/**
|
107 |
-
* Convert old values from key=>value to a multidimensional array of data.
|
108 |
-
*
|
109 |
-
* @since 1.0.0
|
110 |
-
*/
|
111 |
-
protected function get_converted_options() {
|
112 |
-
|
113 |
-
$converted = array();
|
114 |
-
|
115 |
-
foreach ( $this->old_keys as $old_key ) {
|
116 |
-
|
117 |
-
switch ( $old_key ) {
|
118 |
-
case 'pepipost_user':
|
119 |
-
case 'pepipost_pass':
|
120 |
-
case 'pepipost_port':
|
121 |
-
case 'pepipost_ssl':
|
122 |
-
// Do not migrate pepipost options if it's not activated at the moment.
|
123 |
-
if ( 'pepipost' === $this->old_values['mailer'] ) {
|
124 |
-
$shortcut = explode( '_', $old_key );
|
125 |
-
|
126 |
-
if ( $old_key === 'pepipost_ssl' ) {
|
127 |
-
$converted[ $shortcut[0] ]['encryption'] = $this->old_values[ $old_key ];
|
128 |
-
} else {
|
129 |
-
$converted[ $shortcut[0] ][ $shortcut[1] ] = $this->old_values[ $old_key ];
|
130 |
-
}
|
131 |
-
}
|
132 |
-
break;
|
133 |
-
|
134 |
-
case 'smtp_host':
|
135 |
-
case 'smtp_port':
|
136 |
-
case 'smtp_ssl':
|
137 |
-
case 'smtp_auth':
|
138 |
-
case 'smtp_user':
|
139 |
-
case 'smtp_pass':
|
140 |
-
$shortcut = explode( '_', $old_key );
|
141 |
-
|
142 |
-
if ( $old_key === 'smtp_ssl' ) {
|
143 |
-
$converted[ $shortcut[0] ]['encryption'] = $this->old_values[ $old_key ];
|
144 |
-
} elseif ( $old_key === 'smtp_auth' ) {
|
145 |
-
$converted[ $shortcut[0] ][ $shortcut[1] ] = ( $this->old_values[ $old_key ] === 'true' ? 'yes' : 'no' );
|
146 |
-
} else {
|
147 |
-
$converted[ $shortcut[0] ][ $shortcut[1] ] = $this->old_values[ $old_key ];
|
148 |
-
}
|
149 |
-
|
150 |
-
break;
|
151 |
-
|
152 |
-
case 'mail_from':
|
153 |
-
$converted['mail']['from_email'] = $this->old_values[ $old_key ];
|
154 |
-
break;
|
155 |
-
case 'mail_from_name':
|
156 |
-
$converted['mail']['from_name'] = $this->old_values[ $old_key ];
|
157 |
-
break;
|
158 |
-
case 'mail_set_return_path':
|
159 |
-
$converted['mail']['return_path'] = ( $this->old_values[ $old_key ] === 'true' );
|
160 |
-
break;
|
161 |
-
case 'mailer':
|
162 |
-
$converted['mail']['mailer'] = $this->old_values[ $old_key ];
|
163 |
-
break;
|
164 |
-
case 'wp_mail_smtp_am_notifications_hidden':
|
165 |
-
$converted['general']['am_notifications_hidden'] = ( $this->old_values[ $old_key ] === 'true' );
|
166 |
-
break;
|
167 |
-
}
|
168 |
-
}
|
169 |
-
|
170 |
-
$converted = $this->get_converted_constants_options( $converted );
|
171 |
-
|
172 |
-
return $converted;
|
173 |
-
}
|
174 |
-
|
175 |
-
/**
|
176 |
-
* Some users use constants in wp-config.php to define values.
|
177 |
-
* We need to prioritize them and reapply data to options.
|
178 |
-
* Use only those that are actually defined.
|
179 |
-
*
|
180 |
-
* @since 1.0.0
|
181 |
-
*
|
182 |
-
* @param array $converted
|
183 |
-
*
|
184 |
-
* @return array
|
185 |
-
*/
|
186 |
-
protected function get_converted_constants_options( $converted ) {
|
187 |
-
|
188 |
-
// Are we configured via constants?
|
189 |
-
if ( ! defined( 'WPMS_ON' ) || ! WPMS_ON ) {
|
190 |
-
return $converted;
|
191 |
-
}
|
192 |
-
|
193 |
-
/*
|
194 |
-
* Mail settings.
|
195 |
-
*/
|
196 |
-
if ( defined( 'WPMS_MAIL_FROM' ) ) {
|
197 |
-
$converted['mail']['from_email'] = WPMS_MAIL_FROM;
|
198 |
-
}
|
199 |
-
if ( defined( 'WPMS_MAIL_FROM_NAME' ) ) {
|
200 |
-
$converted['mail']['from_name'] = WPMS_MAIL_FROM_NAME;
|
201 |
-
}
|
202 |
-
if ( defined( 'WPMS_MAILER' ) ) {
|
203 |
-
$converted['mail']['return_path'] = WPMS_MAILER;
|
204 |
-
}
|
205 |
-
if ( defined( 'WPMS_SET_RETURN_PATH' ) ) {
|
206 |
-
$converted['mail']['mailer'] = WPMS_SET_RETURN_PATH;
|
207 |
-
}
|
208 |
-
|
209 |
-
/*
|
210 |
-
* SMTP settings.
|
211 |
-
*/
|
212 |
-
if ( defined( 'WPMS_SMTP_HOST' ) ) {
|
213 |
-
$converted['smtp']['host'] = WPMS_SMTP_HOST;
|
214 |
-
}
|
215 |
-
if ( defined( 'WPMS_SMTP_PORT' ) ) {
|
216 |
-
$converted['smtp']['port'] = WPMS_SMTP_PORT;
|
217 |
-
}
|
218 |
-
if ( defined( 'WPMS_SSL' ) ) {
|
219 |
-
$converted['smtp']['ssl'] = WPMS_SSL;
|
220 |
-
}
|
221 |
-
if ( defined( 'WPMS_SMTP_AUTH' ) ) {
|
222 |
-
$converted['smtp']['auth'] = WPMS_SMTP_AUTH;
|
223 |
-
}
|
224 |
-
if ( defined( 'WPMS_SMTP_USER' ) ) {
|
225 |
-
$converted['smtp']['user'] = WPMS_SMTP_USER;
|
226 |
-
}
|
227 |
-
if ( defined( 'WPMS_SMTP_PASS' ) ) {
|
228 |
-
$converted['smtp']['pass'] = WPMS_SMTP_PASS;
|
229 |
-
}
|
230 |
-
|
231 |
-
return $converted;
|
232 |
-
}
|
233 |
-
|
234 |
-
/**
|
235 |
-
* Delete all old values that are stored separately each.
|
236 |
-
*
|
237 |
-
* @since 1.0.0
|
238 |
-
*/
|
239 |
-
protected function clean_deprecated_data() {
|
240 |
-
|
241 |
-
foreach ( $this->old_keys as $old_key ) {
|
242 |
-
delete_option( $old_key );
|
243 |
-
}
|
244 |
-
}
|
245 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Class Migration helps migrate all plugin options saved into DB to a new storage location.
|
7 |
+
*
|
8 |
+
* @since 1.0.0
|
9 |
+
*/
|
10 |
+
class Migration {
|
11 |
+
|
12 |
+
/**
|
13 |
+
* All old values for pre 1.0 version of a plugin.
|
14 |
+
*
|
15 |
+
* @var array
|
16 |
+
*/
|
17 |
+
protected $old_keys = array(
|
18 |
+
'pepipost_ssl',
|
19 |
+
'pepipost_port',
|
20 |
+
'pepipost_pass',
|
21 |
+
'pepipost_user',
|
22 |
+
'smtp_pass',
|
23 |
+
'smtp_user',
|
24 |
+
'smtp_auth',
|
25 |
+
'smtp_ssl',
|
26 |
+
'smtp_port',
|
27 |
+
'smtp_host',
|
28 |
+
'mail_set_return_path',
|
29 |
+
'mailer',
|
30 |
+
'mail_from_name',
|
31 |
+
'mail_from',
|
32 |
+
'wp_mail_smtp_am_notifications_hidden',
|
33 |
+
);
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Old values, taken from $old_keys options.
|
37 |
+
*
|
38 |
+
* @var array
|
39 |
+
*/
|
40 |
+
protected $old_values = array();
|
41 |
+
|
42 |
+
/**
|
43 |
+
* Converted array of data from previous option values.
|
44 |
+
*
|
45 |
+
* @var array
|
46 |
+
*/
|
47 |
+
protected $new_values = array();
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Migration constructor.
|
51 |
+
*
|
52 |
+
* @since 1.0.0
|
53 |
+
*/
|
54 |
+
public function __construct() {
|
55 |
+
|
56 |
+
if ( $this->is_migrated() ) {
|
57 |
+
return;
|
58 |
+
}
|
59 |
+
|
60 |
+
$this->old_values = $this->get_old_values();
|
61 |
+
$this->new_values = $this->get_converted_options();
|
62 |
+
|
63 |
+
Options::init()->set( $this->new_values );
|
64 |
+
|
65 |
+
// Removing all options will be enabled some time in the future.
|
66 |
+
// $this->clean_deprecated_data();
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Whether we already migrated or not.
|
71 |
+
*
|
72 |
+
* @since 1.0.0
|
73 |
+
*
|
74 |
+
* @return bool
|
75 |
+
*/
|
76 |
+
protected function is_migrated() {
|
77 |
+
|
78 |
+
$is_migrated = false;
|
79 |
+
$new_values = get_option( Options::META_KEY, array() );
|
80 |
+
|
81 |
+
if ( ! empty( $new_values ) ) {
|
82 |
+
$is_migrated = true;
|
83 |
+
}
|
84 |
+
|
85 |
+
return $is_migrated;
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Get all old values from DB.
|
90 |
+
*
|
91 |
+
* @since 1.0.0
|
92 |
+
*
|
93 |
+
* @return array
|
94 |
+
*/
|
95 |
+
protected function get_old_values() {
|
96 |
+
|
97 |
+
$old_values = array();
|
98 |
+
|
99 |
+
foreach ( $this->old_keys as $old_key ) {
|
100 |
+
$old_values[ $old_key ] = get_option( $old_key, '' );
|
101 |
+
}
|
102 |
+
|
103 |
+
return $old_values;
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Convert old values from key=>value to a multidimensional array of data.
|
108 |
+
*
|
109 |
+
* @since 1.0.0
|
110 |
+
*/
|
111 |
+
protected function get_converted_options() {
|
112 |
+
|
113 |
+
$converted = array();
|
114 |
+
|
115 |
+
foreach ( $this->old_keys as $old_key ) {
|
116 |
+
|
117 |
+
switch ( $old_key ) {
|
118 |
+
case 'pepipost_user':
|
119 |
+
case 'pepipost_pass':
|
120 |
+
case 'pepipost_port':
|
121 |
+
case 'pepipost_ssl':
|
122 |
+
// Do not migrate pepipost options if it's not activated at the moment.
|
123 |
+
if ( 'pepipost' === $this->old_values['mailer'] ) {
|
124 |
+
$shortcut = explode( '_', $old_key );
|
125 |
+
|
126 |
+
if ( $old_key === 'pepipost_ssl' ) {
|
127 |
+
$converted[ $shortcut[0] ]['encryption'] = $this->old_values[ $old_key ];
|
128 |
+
} else {
|
129 |
+
$converted[ $shortcut[0] ][ $shortcut[1] ] = $this->old_values[ $old_key ];
|
130 |
+
}
|
131 |
+
}
|
132 |
+
break;
|
133 |
+
|
134 |
+
case 'smtp_host':
|
135 |
+
case 'smtp_port':
|
136 |
+
case 'smtp_ssl':
|
137 |
+
case 'smtp_auth':
|
138 |
+
case 'smtp_user':
|
139 |
+
case 'smtp_pass':
|
140 |
+
$shortcut = explode( '_', $old_key );
|
141 |
+
|
142 |
+
if ( $old_key === 'smtp_ssl' ) {
|
143 |
+
$converted[ $shortcut[0] ]['encryption'] = $this->old_values[ $old_key ];
|
144 |
+
} elseif ( $old_key === 'smtp_auth' ) {
|
145 |
+
$converted[ $shortcut[0] ][ $shortcut[1] ] = ( $this->old_values[ $old_key ] === 'true' ? 'yes' : 'no' );
|
146 |
+
} else {
|
147 |
+
$converted[ $shortcut[0] ][ $shortcut[1] ] = $this->old_values[ $old_key ];
|
148 |
+
}
|
149 |
+
|
150 |
+
break;
|
151 |
+
|
152 |
+
case 'mail_from':
|
153 |
+
$converted['mail']['from_email'] = $this->old_values[ $old_key ];
|
154 |
+
break;
|
155 |
+
case 'mail_from_name':
|
156 |
+
$converted['mail']['from_name'] = $this->old_values[ $old_key ];
|
157 |
+
break;
|
158 |
+
case 'mail_set_return_path':
|
159 |
+
$converted['mail']['return_path'] = ( $this->old_values[ $old_key ] === 'true' );
|
160 |
+
break;
|
161 |
+
case 'mailer':
|
162 |
+
$converted['mail']['mailer'] = $this->old_values[ $old_key ];
|
163 |
+
break;
|
164 |
+
case 'wp_mail_smtp_am_notifications_hidden':
|
165 |
+
$converted['general']['am_notifications_hidden'] = ( $this->old_values[ $old_key ] === 'true' );
|
166 |
+
break;
|
167 |
+
}
|
168 |
+
}
|
169 |
+
|
170 |
+
$converted = $this->get_converted_constants_options( $converted );
|
171 |
+
|
172 |
+
return $converted;
|
173 |
+
}
|
174 |
+
|
175 |
+
/**
|
176 |
+
* Some users use constants in wp-config.php to define values.
|
177 |
+
* We need to prioritize them and reapply data to options.
|
178 |
+
* Use only those that are actually defined.
|
179 |
+
*
|
180 |
+
* @since 1.0.0
|
181 |
+
*
|
182 |
+
* @param array $converted
|
183 |
+
*
|
184 |
+
* @return array
|
185 |
+
*/
|
186 |
+
protected function get_converted_constants_options( $converted ) {
|
187 |
+
|
188 |
+
// Are we configured via constants?
|
189 |
+
if ( ! defined( 'WPMS_ON' ) || ! WPMS_ON ) {
|
190 |
+
return $converted;
|
191 |
+
}
|
192 |
+
|
193 |
+
/*
|
194 |
+
* Mail settings.
|
195 |
+
*/
|
196 |
+
if ( defined( 'WPMS_MAIL_FROM' ) ) {
|
197 |
+
$converted['mail']['from_email'] = WPMS_MAIL_FROM;
|
198 |
+
}
|
199 |
+
if ( defined( 'WPMS_MAIL_FROM_NAME' ) ) {
|
200 |
+
$converted['mail']['from_name'] = WPMS_MAIL_FROM_NAME;
|
201 |
+
}
|
202 |
+
if ( defined( 'WPMS_MAILER' ) ) {
|
203 |
+
$converted['mail']['return_path'] = WPMS_MAILER;
|
204 |
+
}
|
205 |
+
if ( defined( 'WPMS_SET_RETURN_PATH' ) ) {
|
206 |
+
$converted['mail']['mailer'] = WPMS_SET_RETURN_PATH;
|
207 |
+
}
|
208 |
+
|
209 |
+
/*
|
210 |
+
* SMTP settings.
|
211 |
+
*/
|
212 |
+
if ( defined( 'WPMS_SMTP_HOST' ) ) {
|
213 |
+
$converted['smtp']['host'] = WPMS_SMTP_HOST;
|
214 |
+
}
|
215 |
+
if ( defined( 'WPMS_SMTP_PORT' ) ) {
|
216 |
+
$converted['smtp']['port'] = WPMS_SMTP_PORT;
|
217 |
+
}
|
218 |
+
if ( defined( 'WPMS_SSL' ) ) {
|
219 |
+
$converted['smtp']['ssl'] = WPMS_SSL;
|
220 |
+
}
|
221 |
+
if ( defined( 'WPMS_SMTP_AUTH' ) ) {
|
222 |
+
$converted['smtp']['auth'] = WPMS_SMTP_AUTH;
|
223 |
+
}
|
224 |
+
if ( defined( 'WPMS_SMTP_USER' ) ) {
|
225 |
+
$converted['smtp']['user'] = WPMS_SMTP_USER;
|
226 |
+
}
|
227 |
+
if ( defined( 'WPMS_SMTP_PASS' ) ) {
|
228 |
+
$converted['smtp']['pass'] = WPMS_SMTP_PASS;
|
229 |
+
}
|
230 |
+
|
231 |
+
return $converted;
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* Delete all old values that are stored separately each.
|
236 |
+
*
|
237 |
+
* @since 1.0.0
|
238 |
+
*/
|
239 |
+
protected function clean_deprecated_data() {
|
240 |
+
|
241 |
+
foreach ( $this->old_keys as $old_key ) {
|
242 |
+
delete_option( $old_key );
|
243 |
+
}
|
244 |
+
}
|
245 |
+
}
|
src/Options.php
CHANGED
@@ -1,469 +1,547 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Class Options to handle all options management.
|
7 |
-
* WordPress does all the heavy work for caching get_option() data,
|
8 |
-
* so we don't have to do that. But we want to minimize cyclomatic complexity
|
9 |
-
* of calling a bunch of WP functions, thus we will cache them in a class as well.
|
10 |
-
*
|
11 |
-
* @since 1.0.0
|
12 |
-
*/
|
13 |
-
class Options {
|
14 |
-
|
15 |
-
/**
|
16 |
-
*
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
*
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
*
|
80 |
-
*
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
*
|
89 |
-
*
|
90 |
-
*
|
91 |
-
*
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
*
|
115 |
-
*
|
116 |
-
*
|
117 |
-
*
|
118 |
-
* @
|
119 |
-
*
|
120 |
-
* @return
|
121 |
-
*/
|
122 |
-
public function
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
case '
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
return $this->is_const_defined( $group, $key ) ?
|
268 |
-
}
|
269 |
-
|
270 |
-
break;
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
case '
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
return
|
321 |
-
}
|
322 |
-
|
323 |
-
break;
|
324 |
-
|
325 |
-
case '
|
326 |
-
switch ( $key ) {
|
327 |
-
case '
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
case '
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Class Options to handle all options management.
|
7 |
+
* WordPress does all the heavy work for caching get_option() data,
|
8 |
+
* so we don't have to do that. But we want to minimize cyclomatic complexity
|
9 |
+
* of calling a bunch of WP functions, thus we will cache them in a class as well.
|
10 |
+
*
|
11 |
+
* @since 1.0.0
|
12 |
+
*/
|
13 |
+
class Options {
|
14 |
+
|
15 |
+
/**
|
16 |
+
* @var array Map of all the default options of the plugin.
|
17 |
+
*/
|
18 |
+
private static $map = array(
|
19 |
+
'mail' => array(
|
20 |
+
'from_name',
|
21 |
+
'from_email',
|
22 |
+
'mailer',
|
23 |
+
'return_path',
|
24 |
+
),
|
25 |
+
'smtp' => array(
|
26 |
+
'host',
|
27 |
+
'port',
|
28 |
+
'encryption',
|
29 |
+
'autotls',
|
30 |
+
'auth',
|
31 |
+
'user',
|
32 |
+
'pass',
|
33 |
+
),
|
34 |
+
'gmail' => array(
|
35 |
+
'client_id',
|
36 |
+
'client_secret',
|
37 |
+
),
|
38 |
+
'mailgun' => array(
|
39 |
+
'api_key',
|
40 |
+
'domain',
|
41 |
+
),
|
42 |
+
'sendgrid' => array(
|
43 |
+
'api_key',
|
44 |
+
),
|
45 |
+
'pepipost' => array(
|
46 |
+
'host',
|
47 |
+
'port',
|
48 |
+
'encryption',
|
49 |
+
'auth',
|
50 |
+
'user',
|
51 |
+
'pass',
|
52 |
+
),
|
53 |
+
);
|
54 |
+
|
55 |
+
/**
|
56 |
+
* That's where plugin options are saved in wp_options table.
|
57 |
+
*
|
58 |
+
* @var string
|
59 |
+
*/
|
60 |
+
const META_KEY = 'wp_mail_smtp';
|
61 |
+
|
62 |
+
/**
|
63 |
+
* All the plugin options.
|
64 |
+
*
|
65 |
+
* @var array
|
66 |
+
*/
|
67 |
+
private $_options = array();
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Init the Options class.
|
71 |
+
*
|
72 |
+
* @since 1.0.0
|
73 |
+
*/
|
74 |
+
public function __construct() {
|
75 |
+
$this->populate_options();
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Initialize all the options, used for chaining.
|
80 |
+
*
|
81 |
+
* One-liner:
|
82 |
+
* Options::init()->get('smtp', 'host');
|
83 |
+
* Options::init()->is_pepipost_active();
|
84 |
+
*
|
85 |
+
* Or multiple-usage:
|
86 |
+
* $options = new Options();
|
87 |
+
* $options->get('smtp', 'host');
|
88 |
+
*
|
89 |
+
* @since 1.0.0
|
90 |
+
*
|
91 |
+
* @return Options
|
92 |
+
*/
|
93 |
+
public static function init() {
|
94 |
+
|
95 |
+
static $instance;
|
96 |
+
|
97 |
+
if ( ! $instance ) {
|
98 |
+
$instance = new self();
|
99 |
+
}
|
100 |
+
|
101 |
+
return $instance;
|
102 |
+
}
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Retrieve all options of the plugin.
|
106 |
+
*
|
107 |
+
* @since 1.0.0
|
108 |
+
*/
|
109 |
+
protected function populate_options() {
|
110 |
+
$this->_options = get_option( self::META_KEY, array() );
|
111 |
+
}
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Get all the options.
|
115 |
+
*
|
116 |
+
* Options::init()->get_all();
|
117 |
+
*
|
118 |
+
* @since 1.0.0
|
119 |
+
*
|
120 |
+
* @return array
|
121 |
+
*/
|
122 |
+
public function get_all() {
|
123 |
+
|
124 |
+
$options = $this->_options;
|
125 |
+
|
126 |
+
foreach ( $options as $group => $g_value ) {
|
127 |
+
foreach ( $g_value as $key => $value ) {
|
128 |
+
$options[ $group ][ $key ] = $this->get( $group, $key );
|
129 |
+
}
|
130 |
+
}
|
131 |
+
|
132 |
+
return apply_filters( 'wp_mail_smtp_options_get_all', $options );
|
133 |
+
}
|
134 |
+
|
135 |
+
/**
|
136 |
+
* Get all the options for a group.
|
137 |
+
*
|
138 |
+
* Options::init()->get_group('smtp') - will return only array of options (or empty array if a key doesn't exist).
|
139 |
+
*
|
140 |
+
* @since 1.0.0
|
141 |
+
*
|
142 |
+
* @param string $group
|
143 |
+
*
|
144 |
+
* @return mixed
|
145 |
+
*/
|
146 |
+
public function get_group( $group ) {
|
147 |
+
|
148 |
+
// Just to feel safe.
|
149 |
+
$group = sanitize_key( $group );
|
150 |
+
|
151 |
+
if ( isset( $this->_options[ $group ] ) ) {
|
152 |
+
|
153 |
+
foreach ( $this->_options[ $group ] as $g_key => $g_value ) {
|
154 |
+
$options[ $group ][ $g_key ] = $this->get( $group, $g_key );
|
155 |
+
}
|
156 |
+
|
157 |
+
return apply_filters( 'wp_mail_smtp_options_get_group', $this->_options[ $group ], $group );
|
158 |
+
}
|
159 |
+
|
160 |
+
return array();
|
161 |
+
}
|
162 |
+
|
163 |
+
/**
|
164 |
+
* Get options by a group and a key.
|
165 |
+
*
|
166 |
+
* Options::init()->get( 'smtp', 'host' ) - will return only SMTP 'host' option.
|
167 |
+
*
|
168 |
+
* @since 1.0.0
|
169 |
+
*
|
170 |
+
* @param string $group
|
171 |
+
* @param string $key
|
172 |
+
*
|
173 |
+
* @return mixed
|
174 |
+
*/
|
175 |
+
public function get( $group, $key ) {
|
176 |
+
|
177 |
+
// Just to feel safe.
|
178 |
+
$group = sanitize_key( $group );
|
179 |
+
$key = sanitize_key( $key );
|
180 |
+
|
181 |
+
// Get the options group.
|
182 |
+
if ( isset( $this->_options[ $group ] ) ) {
|
183 |
+
|
184 |
+
// Get the options key of a group.
|
185 |
+
if ( isset( $this->_options[ $group ][ $key ] ) ) {
|
186 |
+
$value = $this->get_const_value( $group, $key, $this->_options[ $group ][ $key ] );
|
187 |
+
} else {
|
188 |
+
$value = $this->postprocess_key_defaults( $group, $key );
|
189 |
+
}
|
190 |
+
} else {
|
191 |
+
$value = $this->postprocess_key_defaults( $group, $key );
|
192 |
+
}
|
193 |
+
|
194 |
+
return apply_filters( 'wp_mail_smtp_options_get', $value, $group, $key );
|
195 |
+
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* Some options may be non-empty by default,
|
199 |
+
* so we need to postprocess them to convert.
|
200 |
+
*
|
201 |
+
* @since 1.0.0
|
202 |
+
*
|
203 |
+
* @param string $group
|
204 |
+
* @param string $key
|
205 |
+
*
|
206 |
+
* @return mixed
|
207 |
+
*/
|
208 |
+
protected function postprocess_key_defaults( $group, $key ) {
|
209 |
+
|
210 |
+
$value = '';
|
211 |
+
|
212 |
+
switch ( $key ) {
|
213 |
+
case 'return_path':
|
214 |
+
$value = $group === 'mail' ? false : true;
|
215 |
+
break;
|
216 |
+
|
217 |
+
case 'encryption':
|
218 |
+
$value = in_array( $group, array( 'smtp', 'pepipost' ), true ) ? 'none' : $value;
|
219 |
+
break;
|
220 |
+
|
221 |
+
case 'auth':
|
222 |
+
case 'autotls':
|
223 |
+
$value = in_array( $group, array( 'smtp', 'pepipost' ), true ) ? false : true;
|
224 |
+
break;
|
225 |
+
|
226 |
+
case 'pass':
|
227 |
+
$value = $this->get_const_value( $group, $key, $value );
|
228 |
+
break;
|
229 |
+
}
|
230 |
+
|
231 |
+
return apply_filters( 'wp_mail_smtp_options_postprocess_key_defaults', $value, $group, $key );
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* Process the options values through the constants check.
|
236 |
+
* If we have defined associated constant - use it instead of a DB value.
|
237 |
+
* Backward compatibility is hard.
|
238 |
+
* General section of options won't have constants, so we are omitting those checks and just return default value.
|
239 |
+
*
|
240 |
+
* @since 1.0.0
|
241 |
+
*
|
242 |
+
* @param string $group
|
243 |
+
* @param string $key
|
244 |
+
* @param mixed $value
|
245 |
+
*
|
246 |
+
* @return mixed
|
247 |
+
*/
|
248 |
+
protected function get_const_value( $group, $key, $value ) {
|
249 |
+
|
250 |
+
if ( ! $this->is_const_enabled() ) {
|
251 |
+
return $value;
|
252 |
+
}
|
253 |
+
|
254 |
+
switch ( $group ) {
|
255 |
+
case 'mail':
|
256 |
+
switch ( $key ) {
|
257 |
+
case 'from_name':
|
258 |
+
/** @noinspection PhpUndefinedConstantInspection */
|
259 |
+
return $this->is_const_defined( $group, $key ) ? WPMS_MAIL_FROM_NAME : $value;
|
260 |
+
case 'from_email':
|
261 |
+
/** @noinspection PhpUndefinedConstantInspection */
|
262 |
+
return $this->is_const_defined( $group, $key ) ? WPMS_MAIL_FROM : $value;
|
263 |
+
case 'mailer':
|
264 |
+
/** @noinspection PhpUndefinedConstantInspection */
|
265 |
+
return $this->is_const_defined( $group, $key ) ? WPMS_MAILER : $value;
|
266 |
+
case 'return_path':
|
267 |
+
return $this->is_const_defined( $group, $key ) ? true : $value;
|
268 |
+
}
|
269 |
+
|
270 |
+
break;
|
271 |
+
|
272 |
+
case 'smtp':
|
273 |
+
switch ( $key ) {
|
274 |
+
case 'host':
|
275 |
+
/** @noinspection PhpUndefinedConstantInspection */
|
276 |
+
return $this->is_const_defined( $group, $key ) ? WPMS_SMTP_HOST : $value;
|
277 |
+
case 'port':
|
278 |
+
/** @noinspection PhpUndefinedConstantInspection */
|
279 |
+
return $this->is_const_defined( $group, $key ) ? WPMS_SMTP_PORT : $value;
|
280 |
+
case 'encryption':
|
281 |
+
/** @noinspection PhpUndefinedConstantInspection */
|
282 |
+
return $this->is_const_defined( $group, $key )
|
283 |
+
? ( WPMS_SSL === '' ? 'none' : WPMS_SSL )
|
284 |
+
: $value;
|
285 |
+
case 'auth':
|
286 |
+
/** @noinspection PhpUndefinedConstantInspection */
|
287 |
+
return $this->is_const_defined( $group, $key ) ? WPMS_SMTP_AUTH : $value;
|
288 |
+
case 'autotls':
|
289 |
+
/** @noinspection PhpUndefinedConstantInspection */
|
290 |
+
return $this->is_const_defined( $group, $key ) ? WPMS_SMTP_AUTOTLS : $value;
|
291 |
+
case 'user':
|
292 |
+
/** @noinspection PhpUndefinedConstantInspection */
|
293 |
+
return $this->is_const_defined( $group, $key ) ? WPMS_SMTP_USER : $value;
|
294 |
+
case 'pass':
|
295 |
+
/** @noinspection PhpUndefinedConstantInspection */
|
296 |
+
return $this->is_const_defined( $group, $key ) ? WPMS_SMTP_PASS : $value;
|
297 |
+
}
|
298 |
+
|
299 |
+
break;
|
300 |
+
|
301 |
+
case 'gmail':
|
302 |
+
switch ( $key ) {
|
303 |
+
case 'client_id':
|
304 |
+
/** @noinspection PhpUndefinedConstantInspection */
|
305 |
+
return $this->is_const_defined( $group, $key ) ? WPMS_GMAIL_CLIENT_ID : $value;
|
306 |
+
case 'client_secret':
|
307 |
+
/** @noinspection PhpUndefinedConstantInspection */
|
308 |
+
return $this->is_const_defined( $group, $key ) ? WPMS_GMAIL_CLIENT_SECRET : $value;
|
309 |
+
}
|
310 |
+
|
311 |
+
break;
|
312 |
+
|
313 |
+
case 'mailgun':
|
314 |
+
switch ( $key ) {
|
315 |
+
case 'api_key':
|
316 |
+
/** @noinspection PhpUndefinedConstantInspection */
|
317 |
+
return $this->is_const_defined( $group, $key ) ? WPMS_MAILGUN_API_KEY : $value;
|
318 |
+
case 'domain':
|
319 |
+
/** @noinspection PhpUndefinedConstantInspection */
|
320 |
+
return $this->is_const_defined( $group, $key ) ? WPMS_MAILGUN_DOMAIN : $value;
|
321 |
+
}
|
322 |
+
|
323 |
+
break;
|
324 |
+
|
325 |
+
case 'sendgrid':
|
326 |
+
switch ( $key ) {
|
327 |
+
case 'api_key':
|
328 |
+
/** @noinspection PhpUndefinedConstantInspection */
|
329 |
+
return $this->is_const_defined( $group, $key ) ? WPMS_SENDGRID_API_KEY : $value;
|
330 |
+
}
|
331 |
+
|
332 |
+
break;
|
333 |
+
}
|
334 |
+
|
335 |
+
// Always return the default value if nothing from above matches the request.
|
336 |
+
return $value;
|
337 |
+
}
|
338 |
+
|
339 |
+
/**
|
340 |
+
* Whether constants redefinition is enabled or not.
|
341 |
+
*
|
342 |
+
* @since 1.0.0
|
343 |
+
*
|
344 |
+
* @return bool
|
345 |
+
*/
|
346 |
+
public function is_const_enabled() {
|
347 |
+
return defined( 'WPMS_ON' ) && WPMS_ON === true;
|
348 |
+
}
|
349 |
+
|
350 |
+
/**
|
351 |
+
* We need this check to reuse later in admin area,
|
352 |
+
* to distinguish settings fields that were redefined,
|
353 |
+
* and display them differently.
|
354 |
+
*
|
355 |
+
* @since 1.0.0
|
356 |
+
*
|
357 |
+
* @param string $group
|
358 |
+
* @param string $key
|
359 |
+
*
|
360 |
+
* @return bool
|
361 |
+
*/
|
362 |
+
public function is_const_defined( $group, $key ) {
|
363 |
+
|
364 |
+
if ( ! $this->is_const_enabled() ) {
|
365 |
+
return false;
|
366 |
+
}
|
367 |
+
|
368 |
+
// Just to feel safe.
|
369 |
+
$group = sanitize_key( $group );
|
370 |
+
$key = sanitize_key( $key );
|
371 |
+
|
372 |
+
switch ( $group ) {
|
373 |
+
case 'mail':
|
374 |
+
switch ( $key ) {
|
375 |
+
case 'from_name':
|
376 |
+
return defined( 'WPMS_MAIL_FROM_NAME' ) && WPMS_MAIL_FROM_NAME;
|
377 |
+
case 'from_email':
|
378 |
+
return defined( 'WPMS_MAIL_FROM' ) && WPMS_MAIL_FROM;
|
379 |
+
case 'mailer':
|
380 |
+
return defined( 'WPMS_MAILER' ) && WPMS_MAILER;
|
381 |
+
case 'return_path':
|
382 |
+
return defined( 'WPMS_SET_RETURN_PATH' ) && ( WPMS_SET_RETURN_PATH === 'true' || WPMS_SET_RETURN_PATH === true );
|
383 |
+
}
|
384 |
+
|
385 |
+
break;
|
386 |
+
|
387 |
+
case 'smtp':
|
388 |
+
switch ( $key ) {
|
389 |
+
case 'host':
|
390 |
+
return defined( 'WPMS_SMTP_HOST' ) && WPMS_SMTP_HOST;
|
391 |
+
case 'port':
|
392 |
+
return defined( 'WPMS_SMTP_PORT' ) && WPMS_SMTP_PORT;
|
393 |
+
case 'encryption':
|
394 |
+
return defined( 'WPMS_SSL' );
|
395 |
+
case 'auth':
|
396 |
+
return defined( 'WPMS_SMTP_AUTH' ) && WPMS_SMTP_AUTH;
|
397 |
+
case 'autotls':
|
398 |
+
return defined( 'WPMS_SMTP_AUTOTLS' ) && WPMS_SMTP_AUTOTLS;
|
399 |
+
case 'user':
|
400 |
+
return defined( 'WPMS_SMTP_USER' ) && WPMS_SMTP_USER;
|
401 |
+
case 'pass':
|
402 |
+
return defined( 'WPMS_SMTP_PASS' ) && WPMS_SMTP_PASS;
|
403 |
+
}
|
404 |
+
|
405 |
+
break;
|
406 |
+
|
407 |
+
case 'gmail':
|
408 |
+
switch ( $key ) {
|
409 |
+
case 'client_id':
|
410 |
+
return defined( 'WPMS_GMAIL_CLIENT_ID' ) && WPMS_GMAIL_CLIENT_ID;
|
411 |
+
case 'client_secret':
|
412 |
+
return defined( 'WPMS_GMAIL_CLIENT_SECRET' ) && WPMS_GMAIL_CLIENT_SECRET;
|
413 |
+
}
|
414 |
+
|
415 |
+
break;
|
416 |
+
|
417 |
+
case 'mailgun':
|
418 |
+
switch ( $key ) {
|
419 |
+
case 'api_key':
|
420 |
+
return defined( 'WPMS_MAILGUN_API_KEY' ) && WPMS_MAILGUN_API_KEY;
|
421 |
+
case 'domain':
|
422 |
+
return defined( 'WPMS_MAILGUN_DOMAIN' ) && WPMS_MAILGUN_DOMAIN;
|
423 |
+
}
|
424 |
+
|
425 |
+
break;
|
426 |
+
|
427 |
+
case 'sendgrid':
|
428 |
+
switch ( $key ) {
|
429 |
+
case 'api_key':
|
430 |
+
return defined( 'WPMS_SENDGRID_API_KEY' ) && WPMS_SENDGRID_API_KEY;
|
431 |
+
}
|
432 |
+
|
433 |
+
break;
|
434 |
+
}
|
435 |
+
|
436 |
+
return false;
|
437 |
+
}
|
438 |
+
|
439 |
+
/**
|
440 |
+
* Set plugin options, all at once.
|
441 |
+
*
|
442 |
+
* @since 1.0.0
|
443 |
+
*
|
444 |
+
* @param array $options Data to save.
|
445 |
+
*/
|
446 |
+
public function set( $options ) {
|
447 |
+
|
448 |
+
foreach ( (array) $options as $group => $keys ) {
|
449 |
+
foreach ( $keys as $key_name => $key_value ) {
|
450 |
+
switch ( $group ) {
|
451 |
+
case 'mail':
|
452 |
+
switch ( $key_name ) {
|
453 |
+
case 'from_name':
|
454 |
+
case 'mailer':
|
455 |
+
$options[ $group ][ $key_name ] = $this->get_const_value( $group, $key_name, sanitize_text_field( $options[ $group ][ $key_name ] ) );
|
456 |
+
break;
|
457 |
+
case 'from_email':
|
458 |
+
if ( filter_var( $options[ $group ][ $key_name ], FILTER_VALIDATE_EMAIL ) ) {
|
459 |
+
$options[ $group ][ $key_name ] = $this->get_const_value( $group, $key_name, sanitize_email( $options[ $group ][ $key_name ] ) );
|
460 |
+
}
|
461 |
+
break;
|
462 |
+
case 'return_path':
|
463 |
+
$options[ $group ][ $key_name ] = $this->get_const_value( $group, $key_name, (bool) $options[ $group ][ $key_name ] );
|
464 |
+
break;
|
465 |
+
}
|
466 |
+
break;
|
467 |
+
|
468 |
+
case 'general':
|
469 |
+
switch ( $key_name ) {
|
470 |
+
case 'am_notifications_hidden':
|
471 |
+
$options[ $group ][ $key_name ] = (bool) $options[ $group ][ $key_name ];
|
472 |
+
break;
|
473 |
+
}
|
474 |
+
}
|
475 |
+
}
|
476 |
+
}
|
477 |
+
|
478 |
+
if (
|
479 |
+
isset( $options[ $options['mail']['mailer'] ] ) &&
|
480 |
+
in_array( $options['mail']['mailer'], array( 'pepipost', 'smtp', 'sendgrid', 'mailgun', 'gmail' ), true )
|
481 |
+
) {
|
482 |
+
|
483 |
+
$mailer = $options['mail']['mailer'];
|
484 |
+
|
485 |
+
foreach ( $options[ $mailer ] as $key_name => $key_value ) {
|
486 |
+
switch ( $key_name ) {
|
487 |
+
case 'host':
|
488 |
+
case 'user':
|
489 |
+
$options[ $mailer ][ $key_name ] = $this->get_const_value( $mailer, $key_name, sanitize_text_field( $options[ $mailer ][ $key_name ] ) );
|
490 |
+
break;
|
491 |
+
case 'port':
|
492 |
+
$options[ $mailer ][ $key_name ] = $this->get_const_value( $mailer, $key_name, intval( $options[ $mailer ][ $key_name ] ) );
|
493 |
+
break;
|
494 |
+
case 'encryption':
|
495 |
+
$options[ $mailer ][ $key_name ] = $this->get_const_value( $mailer, $key_name, sanitize_text_field( $options[ $mailer ][ $key_name ] ) );
|
496 |
+
break;
|
497 |
+
case 'auth':
|
498 |
+
case 'autotls':
|
499 |
+
$value = $options[ $mailer ][ $key_name ] === 'yes' || $options[ $mailer ][ $key_name ] === true ? true : false;
|
500 |
+
|
501 |
+
$options[ $mailer ][ $key_name ] = $this->get_const_value( $mailer, $key_name, $value );
|
502 |
+
break;
|
503 |
+
|
504 |
+
case 'pass':
|
505 |
+
case 'api_key':
|
506 |
+
case 'domain':
|
507 |
+
case 'client_id':
|
508 |
+
case 'client_secret':
|
509 |
+
case 'auth_code':
|
510 |
+
case 'access_token':
|
511 |
+
// Do not process as they may contain certain special characters, but allow to be overwritten using constants.
|
512 |
+
$options[ $mailer ][ $key_name ] = $this->get_const_value( $mailer, $key_name, $options[ $mailer ][ $key_name ] );
|
513 |
+
break;
|
514 |
+
}
|
515 |
+
}
|
516 |
+
}
|
517 |
+
|
518 |
+
$options = apply_filters( 'wp_mail_smtp_options_set', $options );
|
519 |
+
|
520 |
+
update_option( self::META_KEY, $options );
|
521 |
+
|
522 |
+
// Now we need to re-cache values.
|
523 |
+
$this->populate_options();
|
524 |
+
}
|
525 |
+
|
526 |
+
/**
|
527 |
+
* Check whether the site is using Pepipost or not.
|
528 |
+
*
|
529 |
+
* @since 1.0.0
|
530 |
+
*
|
531 |
+
* @return bool
|
532 |
+
*/
|
533 |
+
public function is_pepipost_active() {
|
534 |
+
return apply_filters( 'wp_mail_smtp_options_is_pepipost_active', $this->get( 'mail', 'mailer' ) === 'pepipost' );
|
535 |
+
}
|
536 |
+
|
537 |
+
/**
|
538 |
+
* Check whether the site is using Pepipost/SMTP as a mailer or not.
|
539 |
+
*
|
540 |
+
* @since 1.1.0
|
541 |
+
*
|
542 |
+
* @return bool
|
543 |
+
*/
|
544 |
+
public function is_mailer_smtp() {
|
545 |
+
return apply_filters( 'wp_mail_smtp_options_is_mailer_smtp', in_array( $this->get( 'mail', 'mailer' ), array( 'pepipost', 'smtp' ), true ) );
|
546 |
+
}
|
547 |
+
}
|
src/Processor.php
CHANGED
@@ -1,170 +1,175 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Class Processor modifies the behaviour of wp_mail() function.
|
7 |
-
*
|
8 |
-
* @since 1.0.0
|
9 |
-
*/
|
10 |
-
class Processor {
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Processor constructor.
|
14 |
-
*
|
15 |
-
* @since 1.0.0
|
16 |
-
*/
|
17 |
-
public function __construct() {
|
18 |
-
$this->hooks();
|
19 |
-
}
|
20 |
-
|
21 |
-
/**
|
22 |
-
* Assign all hooks to proper places.
|
23 |
-
*
|
24 |
-
* @since 1.0.0
|
25 |
-
*/
|
26 |
-
public function hooks() {
|
27 |
-
|
28 |
-
add_action( 'phpmailer_init', array( $this, 'phpmailer_init' ) );
|
29 |
-
|
30 |
-
add_filter( 'wp_mail_from', array( $this, 'filter_mail_from_email' ) );
|
31 |
-
add_filter( 'wp_mail_from_name', array( $this, 'filter_mail_from_name' ), 11 );
|
32 |
-
}
|
33 |
-
|
34 |
-
/**
|
35 |
-
* Redefine certain PHPMailer options with our custom ones.
|
36 |
-
*
|
37 |
-
* @since 1.0.0
|
38 |
-
*
|
39 |
-
* @param \PHPMailer $phpmailer It's passed by reference, so no need to return anything.
|
40 |
-
*/
|
41 |
-
public function phpmailer_init( $phpmailer ) {
|
42 |
-
|
43 |
-
$options = Options
|
44 |
-
$mailer = $options
|
45 |
-
|
46 |
-
// Check that mailer is not blank, and if mailer=smtp, host is not blank.
|
47 |
-
if (
|
48 |
-
! $mailer ||
|
49 |
-
( 'smtp' === $mailer && ! $options
|
50 |
-
) {
|
51 |
-
return;
|
52 |
-
}
|
53 |
-
|
54 |
-
// If the mailer is pepipost, make sure we have a username and password.
|
55 |
-
if (
|
56 |
-
'pepipost' === $mailer &&
|
57 |
-
( ! $options
|
58 |
-
) {
|
59 |
-
return;
|
60 |
-
}
|
61 |
-
|
62 |
-
// Set the mailer type as per config above, this overrides the already called isMail method.
|
63 |
-
// It's basically always 'smtp'.
|
64 |
-
$phpmailer->Mailer = $mailer;
|
65 |
-
|
66 |
-
// Set the Sender (return-path) if required.
|
67 |
-
if (
|
68 |
-
$phpmailer->Sender = $phpmailer->From;
|
69 |
-
}
|
70 |
-
|
71 |
-
// Set the SMTPSecure value, if set to none, leave this blank.
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
$phpmailer->
|
76 |
-
}
|
77 |
-
|
78 |
-
//
|
79 |
-
if ( '
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
$phpmailer->
|
98 |
-
$phpmailer->
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
*
|
114 |
-
*
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
*
|
139 |
-
*
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Class Processor modifies the behaviour of wp_mail() function.
|
7 |
+
*
|
8 |
+
* @since 1.0.0
|
9 |
+
*/
|
10 |
+
class Processor {
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Processor constructor.
|
14 |
+
*
|
15 |
+
* @since 1.0.0
|
16 |
+
*/
|
17 |
+
public function __construct() {
|
18 |
+
$this->hooks();
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Assign all hooks to proper places.
|
23 |
+
*
|
24 |
+
* @since 1.0.0
|
25 |
+
*/
|
26 |
+
public function hooks() {
|
27 |
+
|
28 |
+
add_action( 'phpmailer_init', array( $this, 'phpmailer_init' ) );
|
29 |
+
|
30 |
+
add_filter( 'wp_mail_from', array( $this, 'filter_mail_from_email' ) );
|
31 |
+
add_filter( 'wp_mail_from_name', array( $this, 'filter_mail_from_name' ), 11 );
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Redefine certain PHPMailer options with our custom ones.
|
36 |
+
*
|
37 |
+
* @since 1.0.0
|
38 |
+
*
|
39 |
+
* @param \PHPMailer $phpmailer It's passed by reference, so no need to return anything.
|
40 |
+
*/
|
41 |
+
public function phpmailer_init( $phpmailer ) {
|
42 |
+
|
43 |
+
$options = new Options();
|
44 |
+
$mailer = $options->get( 'mail', 'mailer' );
|
45 |
+
|
46 |
+
// Check that mailer is not blank, and if mailer=smtp, host is not blank.
|
47 |
+
if (
|
48 |
+
! $mailer ||
|
49 |
+
( 'smtp' === $mailer && ! $options->get( 'smtp', 'host' ) )
|
50 |
+
) {
|
51 |
+
return;
|
52 |
+
}
|
53 |
+
|
54 |
+
// If the mailer is pepipost, make sure we have a username and password.
|
55 |
+
if (
|
56 |
+
'pepipost' === $mailer &&
|
57 |
+
( ! $options->get( 'pepipost', 'user' ) && ! $options->get( 'pepipost', 'pass' ) )
|
58 |
+
) {
|
59 |
+
return;
|
60 |
+
}
|
61 |
+
|
62 |
+
// Set the mailer type as per config above, this overrides the already called isMail method.
|
63 |
+
// It's basically always 'smtp'.
|
64 |
+
$phpmailer->Mailer = $mailer;
|
65 |
+
|
66 |
+
// Set the Sender (return-path) if required.
|
67 |
+
if ( $options->get( 'mail', 'return_path' ) ) {
|
68 |
+
$phpmailer->Sender = $phpmailer->From;
|
69 |
+
}
|
70 |
+
|
71 |
+
// Set the SMTPSecure value, if set to none, leave this blank. Possible values: 'ssl', 'tls', ''.
|
72 |
+
if ( 'none' === $options->get( $mailer, 'encryption' ) ) {
|
73 |
+
$phpmailer->SMTPSecure = '';
|
74 |
+
} else {
|
75 |
+
$phpmailer->SMTPSecure = $options->get( $mailer, 'encryption' );
|
76 |
+
}
|
77 |
+
|
78 |
+
// Check if user has disabled SMTPAutoTLS.
|
79 |
+
if ( $options->get( $mailer, 'encryption' ) !== 'tls' && ! $options->get( $mailer, 'autotls' ) ) {
|
80 |
+
$phpmailer->SMTPAutoTLS = false;
|
81 |
+
}
|
82 |
+
|
83 |
+
// If we're sending via SMTP, set the host.
|
84 |
+
if ( 'smtp' === $mailer ) {
|
85 |
+
// Set the other options.
|
86 |
+
$phpmailer->Host = $options->get( $mailer, 'host' );
|
87 |
+
$phpmailer->Port = $options->get( $mailer, 'port' );
|
88 |
+
|
89 |
+
// If we're using smtp auth, set the username & password.
|
90 |
+
if ( $options->get( $mailer, 'auth' ) ) {
|
91 |
+
$phpmailer->SMTPAuth = true;
|
92 |
+
$phpmailer->Username = $options->get( $mailer, 'user' );
|
93 |
+
$phpmailer->Password = $options->get( $mailer, 'pass' );
|
94 |
+
}
|
95 |
+
} elseif ( 'pepipost' === $mailer ) {
|
96 |
+
// Set the Pepipost settings for BC.
|
97 |
+
$phpmailer->Mailer = 'smtp';
|
98 |
+
$phpmailer->Host = 'smtp.pepipost.com';
|
99 |
+
$phpmailer->Port = $options->get( $mailer, 'port' );
|
100 |
+
$phpmailer->SMTPSecure = $options->get( $mailer, 'encryption' ) === 'none' ? '' : $options->get( $mailer, 'encryption' );
|
101 |
+
$phpmailer->SMTPAuth = true;
|
102 |
+
$phpmailer->Username = $options->get( $mailer, 'user' );
|
103 |
+
$phpmailer->Password = $options->get( $mailer, 'pass' );
|
104 |
+
}
|
105 |
+
|
106 |
+
// You can add your own options here.
|
107 |
+
// See the phpmailer documentation for more info: https://github.com/PHPMailer/PHPMailer/tree/5.2-stable.
|
108 |
+
/** @noinspection PhpUnusedLocalVariableInspection It's passed by reference. */
|
109 |
+
$phpmailer = apply_filters( 'wp_mail_smtp_custom_options', $phpmailer );
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Modify the email address that is used for sending emails.
|
114 |
+
*
|
115 |
+
* @since 1.0.0
|
116 |
+
*
|
117 |
+
* @param string $email
|
118 |
+
*
|
119 |
+
* @return string
|
120 |
+
*/
|
121 |
+
public function filter_mail_from_email( $email ) {
|
122 |
+
|
123 |
+
// If the from email is not the default, return it unchanged.
|
124 |
+
if ( $email !== $this->get_default_email() ) {
|
125 |
+
return $email;
|
126 |
+
}
|
127 |
+
|
128 |
+
$from_email = Options::init()->get( 'mail', 'from_email' );
|
129 |
+
|
130 |
+
if ( ! empty( $from_email ) ) {
|
131 |
+
return $from_email;
|
132 |
+
}
|
133 |
+
|
134 |
+
return $email;
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Modify the sender name that is used for sending emails.
|
139 |
+
*
|
140 |
+
* @since 1.0.0
|
141 |
+
*
|
142 |
+
* @param string $name
|
143 |
+
*
|
144 |
+
* @return string
|
145 |
+
*/
|
146 |
+
public function filter_mail_from_name( $name ) {
|
147 |
+
|
148 |
+
if ( 'WordPress' === $name ) {
|
149 |
+
$name = Options::init()->get( 'mail', 'from_name' );
|
150 |
+
}
|
151 |
+
|
152 |
+
return $name;
|
153 |
+
}
|
154 |
+
|
155 |
+
/**
|
156 |
+
* Get the default email address based on domain name.
|
157 |
+
*
|
158 |
+
* @since 1.0.0
|
159 |
+
*
|
160 |
+
* @return string
|
161 |
+
*/
|
162 |
+
public function get_default_email() {
|
163 |
+
|
164 |
+
// In case of CLI we don't have SERVER_NAME, so use host name instead, may be not a domain name.
|
165 |
+
$server_name = ! empty( $_SERVER['SERVER_NAME'] ) ? $_SERVER['SERVER_NAME'] : wp_parse_url( get_home_url( get_current_blog_id() ), PHP_URL_HOST );
|
166 |
+
|
167 |
+
// Get the site domain and get rid of www.
|
168 |
+
$sitename = strtolower( $server_name );
|
169 |
+
if ( substr( $sitename, 0, 4 ) === 'www.' ) {
|
170 |
+
$sitename = substr( $sitename, 4 );
|
171 |
+
}
|
172 |
+
|
173 |
+
return 'wordpress@' . $sitename;
|
174 |
+
}
|
175 |
+
}
|
src/Providers/AuthAbstract.php
CHANGED
@@ -1,22 +1,22 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Providers;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Class AuthAbstract.
|
7 |
-
*
|
8 |
-
* @since 1.0.0
|
9 |
-
*/
|
10 |
-
abstract class AuthAbstract implements AuthInterface {
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Get the url, that users will be redirected back to finish the OAuth process.
|
14 |
-
*
|
15 |
-
* @since 1.0.0
|
16 |
-
*
|
17 |
-
* @return string
|
18 |
-
*/
|
19 |
-
public static function get_plugin_auth_url() {
|
20 |
-
return add_query_arg( 'tab', 'auth', wp_mail_smtp()->get_admin()->get_admin_page_url() );
|
21 |
-
}
|
22 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Providers;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Class AuthAbstract.
|
7 |
+
*
|
8 |
+
* @since 1.0.0
|
9 |
+
*/
|
10 |
+
abstract class AuthAbstract implements AuthInterface {
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Get the url, that users will be redirected back to finish the OAuth process.
|
14 |
+
*
|
15 |
+
* @since 1.0.0
|
16 |
+
*
|
17 |
+
* @return string
|
18 |
+
*/
|
19 |
+
public static function get_plugin_auth_url() {
|
20 |
+
return add_query_arg( 'tab', 'auth', wp_mail_smtp()->get_admin()->get_admin_page_url() );
|
21 |
+
}
|
22 |
+
}
|
src/Providers/AuthInterface.php
CHANGED
@@ -1,19 +1,19 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Providers;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Interface AuthInterface.
|
7 |
-
*
|
8 |
-
* @since 1.0.0
|
9 |
-
*/
|
10 |
-
interface AuthInterface {
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Do something for this Auth implementation.
|
14 |
-
*
|
15 |
-
* @since 1.0.0
|
16 |
-
*/
|
17 |
-
public function process();
|
18 |
-
|
19 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Providers;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Interface AuthInterface.
|
7 |
+
*
|
8 |
+
* @since 1.0.0
|
9 |
+
*/
|
10 |
+
interface AuthInterface {
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Do something for this Auth implementation.
|
14 |
+
*
|
15 |
+
* @since 1.0.0
|
16 |
+
*/
|
17 |
+
public function process();
|
18 |
+
|
19 |
+
}
|
src/Providers/Gmail/Auth.php
CHANGED
@@ -1,299 +1,314 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Providers\Gmail;
|
4 |
-
|
5 |
-
use WPMailSMTP\Options as PluginOptions;
|
6 |
-
use WPMailSMTP\Providers\AuthAbstract;
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Class Auth to request access and refresh tokens.
|
10 |
-
*
|
11 |
-
* @since 1.0.0
|
12 |
-
*/
|
13 |
-
class Auth extends AuthAbstract {
|
14 |
-
|
15 |
-
/**
|
16 |
-
* Gmail options.
|
17 |
-
*
|
18 |
-
* @var array
|
19 |
-
*/
|
20 |
-
private $gmail;
|
21 |
-
|
22 |
-
/**
|
23 |
-
* @var \Google_Client
|
24 |
-
*/
|
25 |
-
private $client;
|
26 |
-
|
27 |
-
/**
|
28 |
-
* @var string
|
29 |
-
*/
|
30 |
-
private $mailer;
|
31 |
-
|
32 |
-
/**
|
33 |
-
* Auth constructor.
|
34 |
-
*
|
35 |
-
* @since 1.0.0
|
36 |
-
*/
|
37 |
-
public function __construct() {
|
38 |
-
|
39 |
-
$options = new PluginOptions();
|
40 |
-
$this->mailer = $options->get( 'mail', 'mailer' );
|
41 |
-
$this->gmail = $options->get_group( $this->mailer );
|
42 |
-
|
43 |
-
if ( $this->is_clients_saved() ) {
|
44 |
-
|
45 |
-
$this->include_google_lib();
|
46 |
-
|
47 |
-
$this->client = $this->get_client();
|
48 |
-
}
|
49 |
-
}
|
50 |
-
|
51 |
-
/**
|
52 |
-
* Use the composer autoloader to include the Google Library and all its dependencies.
|
53 |
-
*
|
54 |
-
* @since 1.0.0
|
55 |
-
*/
|
56 |
-
protected function include_google_lib() {
|
57 |
-
require wp_mail_smtp()->plugin_path . '/vendor/autoload.php';
|
58 |
-
}
|
59 |
-
|
60 |
-
/**
|
61 |
-
* Init and get the Google Client object.
|
62 |
-
*
|
63 |
-
* @since 1.0.0
|
64 |
-
*/
|
65 |
-
public function get_client() {
|
66 |
-
|
67 |
-
// Doesn't load client twice + gives ability to overwrite.
|
68 |
-
if ( ! empty( $this->client ) ) {
|
69 |
-
return $this->client;
|
70 |
-
}
|
71 |
-
|
72 |
-
$client = new \Google_Client(
|
73 |
-
array(
|
74 |
-
'client_id' => $this->gmail['client_id'],
|
75 |
-
'client_secret' => $this->gmail['client_secret'],
|
76 |
-
'redirect_uris' => array(
|
77 |
-
Auth::get_plugin_auth_url(),
|
78 |
-
),
|
79 |
-
)
|
80 |
-
);
|
81 |
-
$client->setAccessType( 'offline' );
|
82 |
-
$client->setApprovalPrompt( 'force' );
|
83 |
-
$client->setIncludeGrantedScopes( true );
|
84 |
-
// We request only the sending capability, as it's what we only need to do.
|
85 |
-
$client->setScopes( array( \Google_Service_Gmail::GMAIL_SEND ) );
|
86 |
-
$client->setRedirectUri( self::get_plugin_auth_url() );
|
87 |
-
|
88 |
-
if (
|
89 |
-
empty( $this->gmail['access_token'] ) &&
|
90 |
-
! empty( $this->gmail['auth_code'] )
|
91 |
-
) {
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
$
|
106 |
-
}
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
if (
|
116 |
-
$
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
if (
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
$
|
182 |
-
}
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
)
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
*
|
223 |
-
*
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
$
|
231 |
-
$
|
232 |
-
|
233 |
-
$
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
*
|
241 |
-
*
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
$
|
249 |
-
$
|
250 |
-
|
251 |
-
$
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
*
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
)
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
*
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
*
|
294 |
-
*
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Providers\Gmail;
|
4 |
+
|
5 |
+
use WPMailSMTP\Options as PluginOptions;
|
6 |
+
use WPMailSMTP\Providers\AuthAbstract;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class Auth to request access and refresh tokens.
|
10 |
+
*
|
11 |
+
* @since 1.0.0
|
12 |
+
*/
|
13 |
+
class Auth extends AuthAbstract {
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Gmail options.
|
17 |
+
*
|
18 |
+
* @var array
|
19 |
+
*/
|
20 |
+
private $gmail;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* @var \Google_Client
|
24 |
+
*/
|
25 |
+
private $client;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* @var string
|
29 |
+
*/
|
30 |
+
private $mailer;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Auth constructor.
|
34 |
+
*
|
35 |
+
* @since 1.0.0
|
36 |
+
*/
|
37 |
+
public function __construct() {
|
38 |
+
|
39 |
+
$options = new PluginOptions();
|
40 |
+
$this->mailer = $options->get( 'mail', 'mailer' );
|
41 |
+
$this->gmail = $options->get_group( $this->mailer );
|
42 |
+
|
43 |
+
if ( $this->is_clients_saved() ) {
|
44 |
+
|
45 |
+
$this->include_google_lib();
|
46 |
+
|
47 |
+
$this->client = $this->get_client();
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Use the composer autoloader to include the Google Library and all its dependencies.
|
53 |
+
*
|
54 |
+
* @since 1.0.0
|
55 |
+
*/
|
56 |
+
protected function include_google_lib() {
|
57 |
+
require wp_mail_smtp()->plugin_path . '/vendor/autoload.php';
|
58 |
+
}
|
59 |
+
|
60 |
+
/**
|
61 |
+
* Init and get the Google Client object.
|
62 |
+
*
|
63 |
+
* @since 1.0.0
|
64 |
+
*/
|
65 |
+
public function get_client() {
|
66 |
+
|
67 |
+
// Doesn't load client twice + gives ability to overwrite.
|
68 |
+
if ( ! empty( $this->client ) ) {
|
69 |
+
return $this->client;
|
70 |
+
}
|
71 |
+
|
72 |
+
$client = new \Google_Client(
|
73 |
+
array(
|
74 |
+
'client_id' => $this->gmail['client_id'],
|
75 |
+
'client_secret' => $this->gmail['client_secret'],
|
76 |
+
'redirect_uris' => array(
|
77 |
+
Auth::get_plugin_auth_url(),
|
78 |
+
),
|
79 |
+
)
|
80 |
+
);
|
81 |
+
$client->setAccessType( 'offline' );
|
82 |
+
$client->setApprovalPrompt( 'force' );
|
83 |
+
$client->setIncludeGrantedScopes( true );
|
84 |
+
// We request only the sending capability, as it's what we only need to do.
|
85 |
+
$client->setScopes( array( \Google_Service_Gmail::GMAIL_SEND ) );
|
86 |
+
$client->setRedirectUri( self::get_plugin_auth_url() );
|
87 |
+
|
88 |
+
if (
|
89 |
+
empty( $this->gmail['access_token'] ) &&
|
90 |
+
! empty( $this->gmail['auth_code'] )
|
91 |
+
) {
|
92 |
+
try {
|
93 |
+
$creds = $client->fetchAccessTokenWithAuthCode( $this->gmail['auth_code'] );
|
94 |
+
} catch ( \Exception $e ) {
|
95 |
+
$creds['error'] = $e->getMessage();
|
96 |
+
}
|
97 |
+
|
98 |
+
// Bail if we have an error.
|
99 |
+
if ( ! empty( $creds['error'] ) ) {
|
100 |
+
// TODO: save this error to display to a user later.
|
101 |
+
return $client;
|
102 |
+
}
|
103 |
+
|
104 |
+
$this->update_access_token( $client->getAccessToken() );
|
105 |
+
$this->update_refresh_token( $client->getRefreshToken() );
|
106 |
+
}
|
107 |
+
|
108 |
+
if ( ! empty( $this->gmail['access_token'] ) ) {
|
109 |
+
$client->setAccessToken( $this->gmail['access_token'] );
|
110 |
+
}
|
111 |
+
|
112 |
+
// Refresh the token if it's expired.
|
113 |
+
if ( $client->isAccessTokenExpired() ) {
|
114 |
+
$refresh = $client->getRefreshToken();
|
115 |
+
if ( empty( $refresh ) && isset( $this->gmail['refresh_token'] ) ) {
|
116 |
+
$refresh = $this->gmail['refresh_token'];
|
117 |
+
}
|
118 |
+
|
119 |
+
if ( ! empty( $refresh ) ) {
|
120 |
+
try {
|
121 |
+
$creds = $client->fetchAccessTokenWithRefreshToken( $refresh );
|
122 |
+
} catch ( \Exception $e ) {
|
123 |
+
$creds['error'] = $e->getMessage();
|
124 |
+
}
|
125 |
+
|
126 |
+
// Bail if we have an error.
|
127 |
+
if ( ! empty( $creds['error'] ) ) {
|
128 |
+
// TODO: save this error to display to a user later.
|
129 |
+
return $client;
|
130 |
+
}
|
131 |
+
|
132 |
+
$this->update_access_token( $client->getAccessToken() );
|
133 |
+
$this->update_refresh_token( $client->getRefreshToken() );
|
134 |
+
}
|
135 |
+
}
|
136 |
+
|
137 |
+
return $client;
|
138 |
+
}
|
139 |
+
|
140 |
+
/**
|
141 |
+
* Get the auth code from the $_GET and save it.
|
142 |
+
* Redirect user back to settings with an error message, if failed.
|
143 |
+
*
|
144 |
+
* @since 1.0.0
|
145 |
+
*/
|
146 |
+
public function process() {
|
147 |
+
|
148 |
+
// We can't process without saved client_id/secret.
|
149 |
+
if ( ! $this->is_clients_saved() ) {
|
150 |
+
wp_redirect(
|
151 |
+
add_query_arg(
|
152 |
+
'error',
|
153 |
+
'google_no_clients',
|
154 |
+
wp_mail_smtp()->get_admin()->get_admin_page_url()
|
155 |
+
)
|
156 |
+
);
|
157 |
+
exit;
|
158 |
+
}
|
159 |
+
|
160 |
+
$code = '';
|
161 |
+
$scope = '';
|
162 |
+
$error = '';
|
163 |
+
|
164 |
+
if ( isset( $_GET['error'] ) ) {
|
165 |
+
$error = sanitize_key( $_GET['error'] );
|
166 |
+
}
|
167 |
+
|
168 |
+
// In case of any error: display a message to a user.
|
169 |
+
if ( ! empty( $error ) ) {
|
170 |
+
wp_redirect(
|
171 |
+
add_query_arg(
|
172 |
+
'error',
|
173 |
+
'google_' . $error,
|
174 |
+
wp_mail_smtp()->get_admin()->get_admin_page_url()
|
175 |
+
)
|
176 |
+
);
|
177 |
+
exit;
|
178 |
+
}
|
179 |
+
|
180 |
+
if ( isset( $_GET['code'] ) ) {
|
181 |
+
$code = $_GET['code'];
|
182 |
+
}
|
183 |
+
if ( isset( $_GET['scope'] ) ) {
|
184 |
+
$scope = urldecode( $_GET['scope'] );
|
185 |
+
}
|
186 |
+
|
187 |
+
// Let's try to get the access token.
|
188 |
+
if (
|
189 |
+
! empty( $code ) &&
|
190 |
+
(
|
191 |
+
$scope === ( \Google_Service_Gmail::GMAIL_SEND . ' ' . \Google_Service_Gmail::MAIL_GOOGLE_COM ) ||
|
192 |
+
$scope === \Google_Service_Gmail::GMAIL_SEND
|
193 |
+
)
|
194 |
+
) {
|
195 |
+
// Save the auth code. So \Google_Client can reuse it to retrieve the access token.
|
196 |
+
$this->update_auth_code( $code );
|
197 |
+
} else {
|
198 |
+
wp_redirect(
|
199 |
+
add_query_arg(
|
200 |
+
'error',
|
201 |
+
'google_no_code_scope',
|
202 |
+
wp_mail_smtp()->get_admin()->get_admin_page_url()
|
203 |
+
)
|
204 |
+
);
|
205 |
+
exit;
|
206 |
+
}
|
207 |
+
|
208 |
+
wp_redirect(
|
209 |
+
add_query_arg(
|
210 |
+
'success',
|
211 |
+
'google_site_linked',
|
212 |
+
wp_mail_smtp()->get_admin()->get_admin_page_url()
|
213 |
+
)
|
214 |
+
);
|
215 |
+
exit;
|
216 |
+
}
|
217 |
+
|
218 |
+
/**
|
219 |
+
* Update access token in our DB.
|
220 |
+
*
|
221 |
+
* @since 1.0.0
|
222 |
+
*
|
223 |
+
* @param array $token
|
224 |
+
*/
|
225 |
+
protected function update_access_token( $token ) {
|
226 |
+
|
227 |
+
$options = new PluginOptions();
|
228 |
+
$all = $options->get_all();
|
229 |
+
|
230 |
+
$all[ $this->mailer ]['access_token'] = $token;
|
231 |
+
$this->gmail['access_token'] = $token;
|
232 |
+
|
233 |
+
$options->set( $all );
|
234 |
+
}
|
235 |
+
|
236 |
+
/**
|
237 |
+
* Update refresh token in our DB.
|
238 |
+
*
|
239 |
+
* @since 1.0.0
|
240 |
+
*
|
241 |
+
* @param array $token
|
242 |
+
*/
|
243 |
+
protected function update_refresh_token( $token ) {
|
244 |
+
|
245 |
+
$options = new PluginOptions();
|
246 |
+
$all = $options->get_all();
|
247 |
+
|
248 |
+
$all[ $this->mailer ]['refresh_token'] = $token;
|
249 |
+
$this->gmail['refresh_token'] = $token;
|
250 |
+
|
251 |
+
$options->set( $all );
|
252 |
+
}
|
253 |
+
|
254 |
+
/**
|
255 |
+
* Update auth code in our DB.
|
256 |
+
*
|
257 |
+
* @since 1.0.0
|
258 |
+
*
|
259 |
+
* @param string $code
|
260 |
+
*/
|
261 |
+
protected function update_auth_code( $code ) {
|
262 |
+
|
263 |
+
$options = new PluginOptions();
|
264 |
+
$all = $options->get_all();
|
265 |
+
|
266 |
+
$all[ $this->mailer ]['auth_code'] = $code;
|
267 |
+
$this->gmail['auth_code'] = $code;
|
268 |
+
|
269 |
+
|
270 |
+
$options->set( $all );
|
271 |
+
}
|
272 |
+
|
273 |
+
/**
|
274 |
+
* Get the auth URL used to proceed to Google to request access to send emails.
|
275 |
+
*
|
276 |
+
* @since 1.0.0
|
277 |
+
*
|
278 |
+
* @return string
|
279 |
+
*/
|
280 |
+
public function get_google_auth_url() {
|
281 |
+
if (
|
282 |
+
! empty( $this->client ) &&
|
283 |
+
class_exists( 'Google_Client', false ) &&
|
284 |
+
$this->client instanceof \Google_Client
|
285 |
+
) {
|
286 |
+
return filter_var( $this->client->createAuthUrl(), FILTER_SANITIZE_URL );
|
287 |
+
}
|
288 |
+
|
289 |
+
return '';
|
290 |
+
}
|
291 |
+
|
292 |
+
/**
|
293 |
+
* Whether user saved Client ID and Client Secret or not.
|
294 |
+
* Both options are required.
|
295 |
+
*
|
296 |
+
* @since 1.0.0
|
297 |
+
*
|
298 |
+
* @return bool
|
299 |
+
*/
|
300 |
+
public function is_clients_saved() {
|
301 |
+
return ! empty( $this->gmail['client_id'] ) && ! empty( $this->gmail['client_secret'] );
|
302 |
+
}
|
303 |
+
|
304 |
+
/**
|
305 |
+
* Whether we have an access and refresh tokens or not.
|
306 |
+
*
|
307 |
+
* @since 1.0.0
|
308 |
+
*
|
309 |
+
* @return bool
|
310 |
+
*/
|
311 |
+
public function is_auth_required() {
|
312 |
+
return empty( $this->gmail['access_token'] ) || empty( $this->gmail['refresh_token'] );
|
313 |
+
}
|
314 |
+
}
|
src/Providers/Gmail/Mailer.php
CHANGED
@@ -1,173 +1,173 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Providers\Gmail;
|
4 |
-
|
5 |
-
use WPMailSMTP\Providers\MailerAbstract;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Class Mailer.
|
9 |
-
*
|
10 |
-
* @since 1.0.0
|
11 |
-
*/
|
12 |
-
class Mailer extends MailerAbstract {
|
13 |
-
|
14 |
-
/**
|
15 |
-
* URL to make an API request to.
|
16 |
-
* Not used for Gmail, as we are using its API.
|
17 |
-
*
|
18 |
-
* @var string
|
19 |
-
*/
|
20 |
-
protected $url = 'https://www.googleapis.com/upload/gmail/v1/users/userId/messages/send';
|
21 |
-
|
22 |
-
/**
|
23 |
-
* Gmail custom Auth library.
|
24 |
-
*
|
25 |
-
* @var Auth
|
26 |
-
*/
|
27 |
-
protected $auth;
|
28 |
-
|
29 |
-
/**
|
30 |
-
* Gmail message.
|
31 |
-
*
|
32 |
-
* @var \Google_Service_Gmail_Message
|
33 |
-
*/
|
34 |
-
protected $message;
|
35 |
-
|
36 |
-
/**
|
37 |
-
* Mailer constructor.
|
38 |
-
*
|
39 |
-
* @since 1.0.0
|
40 |
-
*
|
41 |
-
* @param \WPMailSMTP\MailCatcher $phpmailer
|
42 |
-
*/
|
43 |
-
public function __construct( $phpmailer ) {
|
44 |
-
parent::__construct( $phpmailer );
|
45 |
-
|
46 |
-
if ( ! $this->is_php_compatible() ) {
|
47 |
-
return;
|
48 |
-
}
|
49 |
-
|
50 |
-
// Include the Google library.
|
51 |
-
require wp_mail_smtp()->plugin_path . '/vendor/autoload.php';
|
52 |
-
|
53 |
-
$this->auth = new Auth();
|
54 |
-
$this->message = new \Google_Service_Gmail_Message();
|
55 |
-
}
|
56 |
-
|
57 |
-
/**
|
58 |
-
* Set email FROM.
|
59 |
-
*
|
60 |
-
* @since 1.0.0
|
61 |
-
*
|
62 |
-
* @param string $email
|
63 |
-
* @param string $name
|
64 |
-
*/
|
65 |
-
public function set_from( $email, $name ) {
|
66 |
-
}
|
67 |
-
|
68 |
-
/**
|
69 |
-
* Set a bunch of email recipients: to, cc, bcc.
|
70 |
-
*
|
71 |
-
* @since 1.0.0
|
72 |
-
*
|
73 |
-
* @param array $recipients
|
74 |
-
*/
|
75 |
-
public function set_recipients( $recipients ) {
|
76 |
-
}
|
77 |
-
|
78 |
-
/**
|
79 |
-
* Set the email content.
|
80 |
-
*
|
81 |
-
* @since 1.0.0
|
82 |
-
*
|
83 |
-
* @param string|array $content
|
84 |
-
*/
|
85 |
-
public function set_content( $content ) {
|
86 |
-
}
|
87 |
-
|
88 |
-
/**
|
89 |
-
* Set the email attachments.
|
90 |
-
*
|
91 |
-
* @since 1.0.0
|
92 |
-
*
|
93 |
-
* @param array $attachments
|
94 |
-
*/
|
95 |
-
public function set_attachments( $attachments ) {
|
96 |
-
}
|
97 |
-
|
98 |
-
/**
|
99 |
-
* Set the email reply_to option.
|
100 |
-
*
|
101 |
-
* @since 1.0.0
|
102 |
-
*
|
103 |
-
* @param array $reply_to
|
104 |
-
*/
|
105 |
-
public function set_reply_to( $reply_to ) {
|
106 |
-
}
|
107 |
-
|
108 |
-
/**
|
109 |
-
* Set the email return_path (when supported).
|
110 |
-
*
|
111 |
-
* @since 1.0.0
|
112 |
-
*
|
113 |
-
* @param string $email
|
114 |
-
*/
|
115 |
-
public function set_return_path( $email ) {
|
116 |
-
}
|
117 |
-
|
118 |
-
/**
|
119 |
-
* Use Google API Services to send emails.
|
120 |
-
*
|
121 |
-
* @since 1.0.0
|
122 |
-
*/
|
123 |
-
public function send() {
|
124 |
-
|
125 |
-
// Get the raw MIME email using \PHPMailer data.
|
126 |
-
$mime = $this->phpmailer->getSentMIMEMessage();
|
127 |
-
$data = base64_encode( $mime );
|
128 |
-
$data = str_replace( array( '+', '/', '=' ), array( '-', '_', '' ), $data ); // url safe.
|
129 |
-
$this->message->setRaw( $data );
|
130 |
-
|
131 |
-
$service = new \Google_Service_Gmail( $this->auth->get_client() );
|
132 |
-
|
133 |
-
try {
|
134 |
-
$response = $service->users_messages->send( 'me', $this->message );
|
135 |
-
|
136 |
-
$this->process_response( $response );
|
137 |
-
} catch ( \Exception $e ) {
|
138 |
-
// TODO: save here the error message to display to a user later.
|
139 |
-
return;
|
140 |
-
}
|
141 |
-
}
|
142 |
-
|
143 |
-
/**
|
144 |
-
* Save response from the API to use it later.
|
145 |
-
*
|
146 |
-
* @since 1.0.0
|
147 |
-
*
|
148 |
-
* @param \Google_Service_Gmail_Message $response
|
149 |
-
*/
|
150 |
-
protected function process_response( $response ) {
|
151 |
-
$this->response = $response;
|
152 |
-
}
|
153 |
-
|
154 |
-
/**
|
155 |
-
* Check whether the email was sent.
|
156 |
-
*
|
157 |
-
* @since 1.0.0
|
158 |
-
*
|
159 |
-
* @return bool
|
160 |
-
*/
|
161 |
-
public function is_email_sent() {
|
162 |
-
$is_sent = false;
|
163 |
-
|
164 |
-
if ( method_exists( $this->response, 'getId' ) ) {
|
165 |
-
$message_id = $this->response->getId();
|
166 |
-
if ( ! empty( $message_id ) ) {
|
167 |
-
return true;
|
168 |
-
}
|
169 |
-
}
|
170 |
-
|
171 |
-
return $is_sent;
|
172 |
-
}
|
173 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Providers\Gmail;
|
4 |
+
|
5 |
+
use WPMailSMTP\Providers\MailerAbstract;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class Mailer.
|
9 |
+
*
|
10 |
+
* @since 1.0.0
|
11 |
+
*/
|
12 |
+
class Mailer extends MailerAbstract {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* URL to make an API request to.
|
16 |
+
* Not used for Gmail, as we are using its API.
|
17 |
+
*
|
18 |
+
* @var string
|
19 |
+
*/
|
20 |
+
protected $url = 'https://www.googleapis.com/upload/gmail/v1/users/userId/messages/send';
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Gmail custom Auth library.
|
24 |
+
*
|
25 |
+
* @var Auth
|
26 |
+
*/
|
27 |
+
protected $auth;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Gmail message.
|
31 |
+
*
|
32 |
+
* @var \Google_Service_Gmail_Message
|
33 |
+
*/
|
34 |
+
protected $message;
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Mailer constructor.
|
38 |
+
*
|
39 |
+
* @since 1.0.0
|
40 |
+
*
|
41 |
+
* @param \WPMailSMTP\MailCatcher $phpmailer
|
42 |
+
*/
|
43 |
+
public function __construct( $phpmailer ) {
|
44 |
+
parent::__construct( $phpmailer );
|
45 |
+
|
46 |
+
if ( ! $this->is_php_compatible() ) {
|
47 |
+
return;
|
48 |
+
}
|
49 |
+
|
50 |
+
// Include the Google library.
|
51 |
+
require wp_mail_smtp()->plugin_path . '/vendor/autoload.php';
|
52 |
+
|
53 |
+
$this->auth = new Auth();
|
54 |
+
$this->message = new \Google_Service_Gmail_Message();
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Set email FROM.
|
59 |
+
*
|
60 |
+
* @since 1.0.0
|
61 |
+
*
|
62 |
+
* @param string $email
|
63 |
+
* @param string $name
|
64 |
+
*/
|
65 |
+
public function set_from( $email, $name ) {
|
66 |
+
}
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Set a bunch of email recipients: to, cc, bcc.
|
70 |
+
*
|
71 |
+
* @since 1.0.0
|
72 |
+
*
|
73 |
+
* @param array $recipients
|
74 |
+
*/
|
75 |
+
public function set_recipients( $recipients ) {
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Set the email content.
|
80 |
+
*
|
81 |
+
* @since 1.0.0
|
82 |
+
*
|
83 |
+
* @param string|array $content
|
84 |
+
*/
|
85 |
+
public function set_content( $content ) {
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Set the email attachments.
|
90 |
+
*
|
91 |
+
* @since 1.0.0
|
92 |
+
*
|
93 |
+
* @param array $attachments
|
94 |
+
*/
|
95 |
+
public function set_attachments( $attachments ) {
|
96 |
+
}
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Set the email reply_to option.
|
100 |
+
*
|
101 |
+
* @since 1.0.0
|
102 |
+
*
|
103 |
+
* @param array $reply_to
|
104 |
+
*/
|
105 |
+
public function set_reply_to( $reply_to ) {
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Set the email return_path (when supported).
|
110 |
+
*
|
111 |
+
* @since 1.0.0
|
112 |
+
*
|
113 |
+
* @param string $email
|
114 |
+
*/
|
115 |
+
public function set_return_path( $email ) {
|
116 |
+
}
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Use Google API Services to send emails.
|
120 |
+
*
|
121 |
+
* @since 1.0.0
|
122 |
+
*/
|
123 |
+
public function send() {
|
124 |
+
|
125 |
+
// Get the raw MIME email using \PHPMailer data.
|
126 |
+
$mime = $this->phpmailer->getSentMIMEMessage();
|
127 |
+
$data = base64_encode( $mime );
|
128 |
+
$data = str_replace( array( '+', '/', '=' ), array( '-', '_', '' ), $data ); // url safe.
|
129 |
+
$this->message->setRaw( $data );
|
130 |
+
|
131 |
+
$service = new \Google_Service_Gmail( $this->auth->get_client() );
|
132 |
+
|
133 |
+
try {
|
134 |
+
$response = $service->users_messages->send( 'me', $this->message );
|
135 |
+
|
136 |
+
$this->process_response( $response );
|
137 |
+
} catch ( \Exception $e ) {
|
138 |
+
// TODO: save here the error message to display to a user later.
|
139 |
+
return;
|
140 |
+
}
|
141 |
+
}
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Save response from the API to use it later.
|
145 |
+
*
|
146 |
+
* @since 1.0.0
|
147 |
+
*
|
148 |
+
* @param \Google_Service_Gmail_Message $response
|
149 |
+
*/
|
150 |
+
protected function process_response( $response ) {
|
151 |
+
$this->response = $response;
|
152 |
+
}
|
153 |
+
|
154 |
+
/**
|
155 |
+
* Check whether the email was sent.
|
156 |
+
*
|
157 |
+
* @since 1.0.0
|
158 |
+
*
|
159 |
+
* @return bool
|
160 |
+
*/
|
161 |
+
public function is_email_sent() {
|
162 |
+
$is_sent = false;
|
163 |
+
|
164 |
+
if ( method_exists( $this->response, 'getId' ) ) {
|
165 |
+
$message_id = $this->response->getId();
|
166 |
+
if ( ! empty( $message_id ) ) {
|
167 |
+
return true;
|
168 |
+
}
|
169 |
+
}
|
170 |
+
|
171 |
+
return $is_sent;
|
172 |
+
}
|
173 |
+
}
|
src/Providers/Gmail/Options.php
CHANGED
@@ -1,131 +1,131 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Providers\Gmail;
|
4 |
-
|
5 |
-
use WPMailSMTP\Providers\OptionAbstract;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Class Option.
|
9 |
-
*
|
10 |
-
* @since 1.0.0
|
11 |
-
*/
|
12 |
-
class Options extends OptionAbstract {
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Mailgun constructor.
|
16 |
-
*
|
17 |
-
* @since 1.0.0
|
18 |
-
*/
|
19 |
-
public function __construct() {
|
20 |
-
|
21 |
-
parent::__construct(
|
22 |
-
array(
|
23 |
-
'logo_url' => wp_mail_smtp()->plugin_url . '/assets/images/gmail.png',
|
24 |
-
'slug' => 'gmail',
|
25 |
-
'title' => esc_html__( 'Gmail', 'wp-mail-smtp' ),
|
26 |
-
'description' => sprintf(
|
27 |
-
wp_kses(
|
28 |
-
/* translators: %1$s - opening link tag; %2$s - closing link tag. */
|
29 |
-
__( 'Send emails using your Gmail or G Suite (formerly Google Apps) account, all while keeping your login credentials safe. Other Google SMTP methods require enabling less secure apps in your account and entering your password. However, this integration uses the Google API to improve email delivery issues while keeping your site secure.<br><br>Read our %1$sGmail documentation%2$s to learn how to configure Gmail or G Suite.', 'wp-mail-smtp' ),
|
30 |
-
array(
|
31 |
-
'br' => array(),
|
32 |
-
'a' => array(
|
33 |
-
'href' => array(),
|
34 |
-
'rel' => array(),
|
35 |
-
'target' => array(),
|
36 |
-
),
|
37 |
-
)
|
38 |
-
),
|
39 |
-
'<a href="https://wpforms.com/how-to-securely-send-wordpress-emails-using-gmail-smtp/" target="_blank" rel="noopener noreferrer">',
|
40 |
-
'</a>'
|
41 |
-
),
|
42 |
-
'php' => '5.5',
|
43 |
-
)
|
44 |
-
);
|
45 |
-
}
|
46 |
-
|
47 |
-
/**
|
48 |
-
* @inheritdoc
|
49 |
-
*/
|
50 |
-
public function display_options() {
|
51 |
-
|
52 |
-
// Do not display options if PHP version is not correct.
|
53 |
-
if ( ! $this->is_php_correct() ) {
|
54 |
-
$this->display_php_warning();
|
55 |
-
|
56 |
-
return;
|
57 |
-
}
|
58 |
-
?>
|
59 |
-
|
60 |
-
<!-- Client ID -->
|
61 |
-
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_id" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
62 |
-
<div class="wp-mail-smtp-setting-label">
|
63 |
-
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_id"><?php esc_html_e( 'Client ID', 'wp-mail-smtp' ); ?></label>
|
64 |
-
</div>
|
65 |
-
<div class="wp-mail-smtp-setting-field">
|
66 |
-
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][client_id]" type="text"
|
67 |
-
value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'client_id' ) ); ?>"
|
68 |
-
<?php echo $this->options->is_const_defined( $this->get_slug(), 'client_id' ) ? 'disabled' : ''; ?>
|
69 |
-
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_id" spellcheck="false"
|
70 |
-
/>
|
71 |
-
</div>
|
72 |
-
</div>
|
73 |
-
|
74 |
-
<!-- Client Secret -->
|
75 |
-
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_secret" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
76 |
-
<div class="wp-mail-smtp-setting-label">
|
77 |
-
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_secret"><?php esc_html_e( 'Client Secret', 'wp-mail-smtp' ); ?></label>
|
78 |
-
</div>
|
79 |
-
<div class="wp-mail-smtp-setting-field">
|
80 |
-
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][client_secret]" type="text"
|
81 |
-
value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'client_secret' ) ); ?>"
|
82 |
-
<?php echo $this->options->is_const_defined( $this->get_slug(), 'client_secret' ) ? 'disabled' : ''; ?>
|
83 |
-
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_secret" spellcheck="false"
|
84 |
-
/>
|
85 |
-
</div>
|
86 |
-
</div>
|
87 |
-
|
88 |
-
<!-- Authorized redirect URI -->
|
89 |
-
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_redirect" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
90 |
-
<div class="wp-mail-smtp-setting-label">
|
91 |
-
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_redirect"><?php esc_html_e( 'Authorized redirect URI', 'wp-mail-smtp' ); ?></label>
|
92 |
-
</div>
|
93 |
-
<div class="wp-mail-smtp-setting-field">
|
94 |
-
<input type="text" readonly="readonly"
|
95 |
-
value="<?php echo esc_attr( Auth::get_plugin_auth_url() ); ?>"
|
96 |
-
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_redirect"
|
97 |
-
/>
|
98 |
-
<button type="button" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-light-grey wp-mail-smtp-setting-copy"
|
99 |
-
title="<?php esc_attr_e( 'Copy URL to clipboard', 'wp-mail-smtp' ); ?>"
|
100 |
-
data-source_id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_redirect">
|
101 |
-
<span class="dashicons dashicons-admin-page"></span>
|
102 |
-
</button>
|
103 |
-
<p class="desc">
|
104 |
-
<?php esc_html_e( 'This is the path on your site that you will be redirected to after you have authenticated with Google.', 'wp-mail-smtp' ); ?>
|
105 |
-
<br>
|
106 |
-
<?php esc_html_e( 'You need to copy this URL into "Authorized redirect URIs" field for you web application on Google APIs site for your project there.', 'wp-mail-smtp' ); ?>
|
107 |
-
</p>
|
108 |
-
</div>
|
109 |
-
</div>
|
110 |
-
|
111 |
-
<!-- Auth users button -->
|
112 |
-
<?php $auth = new Auth(); ?>
|
113 |
-
<?php if ( $auth->is_clients_saved() && $auth->is_auth_required() ) : ?>
|
114 |
-
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-authorize" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
115 |
-
<div class="wp-mail-smtp-setting-label">
|
116 |
-
<label><?php esc_html_e( 'Authorize', 'wp-mail-smtp' ); ?></label>
|
117 |
-
</div>
|
118 |
-
<div class="wp-mail-smtp-setting-field">
|
119 |
-
<a href="<?php echo esc_url( $auth->get_google_auth_url() ); ?>" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-orange">
|
120 |
-
<?php esc_html_e( 'Allow plugin to send emails using your Google account', 'wp-mail-smtp' ); ?>
|
121 |
-
</a>
|
122 |
-
<p class="desc">
|
123 |
-
<?php esc_html_e( 'Click the button above to confirm authorization.', 'wp-mail-smtp' ); ?>
|
124 |
-
</p>
|
125 |
-
</div>
|
126 |
-
</div>
|
127 |
-
<?php endif; ?>
|
128 |
-
|
129 |
-
<?php
|
130 |
-
}
|
131 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Providers\Gmail;
|
4 |
+
|
5 |
+
use WPMailSMTP\Providers\OptionAbstract;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class Option.
|
9 |
+
*
|
10 |
+
* @since 1.0.0
|
11 |
+
*/
|
12 |
+
class Options extends OptionAbstract {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Mailgun constructor.
|
16 |
+
*
|
17 |
+
* @since 1.0.0
|
18 |
+
*/
|
19 |
+
public function __construct() {
|
20 |
+
|
21 |
+
parent::__construct(
|
22 |
+
array(
|
23 |
+
'logo_url' => wp_mail_smtp()->plugin_url . '/assets/images/gmail.png',
|
24 |
+
'slug' => 'gmail',
|
25 |
+
'title' => esc_html__( 'Gmail', 'wp-mail-smtp' ),
|
26 |
+
'description' => sprintf(
|
27 |
+
wp_kses(
|
28 |
+
/* translators: %1$s - opening link tag; %2$s - closing link tag. */
|
29 |
+
__( 'Send emails using your Gmail or G Suite (formerly Google Apps) account, all while keeping your login credentials safe. Other Google SMTP methods require enabling less secure apps in your account and entering your password. However, this integration uses the Google API to improve email delivery issues while keeping your site secure.<br><br>Read our %1$sGmail documentation%2$s to learn how to configure Gmail or G Suite.', 'wp-mail-smtp' ),
|
30 |
+
array(
|
31 |
+
'br' => array(),
|
32 |
+
'a' => array(
|
33 |
+
'href' => array(),
|
34 |
+
'rel' => array(),
|
35 |
+
'target' => array(),
|
36 |
+
),
|
37 |
+
)
|
38 |
+
),
|
39 |
+
'<a href="https://wpforms.com/how-to-securely-send-wordpress-emails-using-gmail-smtp/" target="_blank" rel="noopener noreferrer">',
|
40 |
+
'</a>'
|
41 |
+
),
|
42 |
+
'php' => '5.5',
|
43 |
+
)
|
44 |
+
);
|
45 |
+
}
|
46 |
+
|
47 |
+
/**
|
48 |
+
* @inheritdoc
|
49 |
+
*/
|
50 |
+
public function display_options() {
|
51 |
+
|
52 |
+
// Do not display options if PHP version is not correct.
|
53 |
+
if ( ! $this->is_php_correct() ) {
|
54 |
+
$this->display_php_warning();
|
55 |
+
|
56 |
+
return;
|
57 |
+
}
|
58 |
+
?>
|
59 |
+
|
60 |
+
<!-- Client ID -->
|
61 |
+
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_id" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
62 |
+
<div class="wp-mail-smtp-setting-label">
|
63 |
+
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_id"><?php esc_html_e( 'Client ID', 'wp-mail-smtp' ); ?></label>
|
64 |
+
</div>
|
65 |
+
<div class="wp-mail-smtp-setting-field">
|
66 |
+
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][client_id]" type="text"
|
67 |
+
value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'client_id' ) ); ?>"
|
68 |
+
<?php echo $this->options->is_const_defined( $this->get_slug(), 'client_id' ) ? 'disabled' : ''; ?>
|
69 |
+
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_id" spellcheck="false"
|
70 |
+
/>
|
71 |
+
</div>
|
72 |
+
</div>
|
73 |
+
|
74 |
+
<!-- Client Secret -->
|
75 |
+
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_secret" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
76 |
+
<div class="wp-mail-smtp-setting-label">
|
77 |
+
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_secret"><?php esc_html_e( 'Client Secret', 'wp-mail-smtp' ); ?></label>
|
78 |
+
</div>
|
79 |
+
<div class="wp-mail-smtp-setting-field">
|
80 |
+
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][client_secret]" type="text"
|
81 |
+
value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'client_secret' ) ); ?>"
|
82 |
+
<?php echo $this->options->is_const_defined( $this->get_slug(), 'client_secret' ) ? 'disabled' : ''; ?>
|
83 |
+
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_secret" spellcheck="false"
|
84 |
+
/>
|
85 |
+
</div>
|
86 |
+
</div>
|
87 |
+
|
88 |
+
<!-- Authorized redirect URI -->
|
89 |
+
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_redirect" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
90 |
+
<div class="wp-mail-smtp-setting-label">
|
91 |
+
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_redirect"><?php esc_html_e( 'Authorized redirect URI', 'wp-mail-smtp' ); ?></label>
|
92 |
+
</div>
|
93 |
+
<div class="wp-mail-smtp-setting-field">
|
94 |
+
<input type="text" readonly="readonly"
|
95 |
+
value="<?php echo esc_attr( Auth::get_plugin_auth_url() ); ?>"
|
96 |
+
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_redirect"
|
97 |
+
/>
|
98 |
+
<button type="button" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-light-grey wp-mail-smtp-setting-copy"
|
99 |
+
title="<?php esc_attr_e( 'Copy URL to clipboard', 'wp-mail-smtp' ); ?>"
|
100 |
+
data-source_id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_redirect">
|
101 |
+
<span class="dashicons dashicons-admin-page"></span>
|
102 |
+
</button>
|
103 |
+
<p class="desc">
|
104 |
+
<?php esc_html_e( 'This is the path on your site that you will be redirected to after you have authenticated with Google.', 'wp-mail-smtp' ); ?>
|
105 |
+
<br>
|
106 |
+
<?php esc_html_e( 'You need to copy this URL into "Authorized redirect URIs" field for you web application on Google APIs site for your project there.', 'wp-mail-smtp' ); ?>
|
107 |
+
</p>
|
108 |
+
</div>
|
109 |
+
</div>
|
110 |
+
|
111 |
+
<!-- Auth users button -->
|
112 |
+
<?php $auth = new Auth(); ?>
|
113 |
+
<?php if ( $auth->is_clients_saved() && $auth->is_auth_required() ) : ?>
|
114 |
+
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-authorize" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
115 |
+
<div class="wp-mail-smtp-setting-label">
|
116 |
+
<label><?php esc_html_e( 'Authorize', 'wp-mail-smtp' ); ?></label>
|
117 |
+
</div>
|
118 |
+
<div class="wp-mail-smtp-setting-field">
|
119 |
+
<a href="<?php echo esc_url( $auth->get_google_auth_url() ); ?>" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-orange">
|
120 |
+
<?php esc_html_e( 'Allow plugin to send emails using your Google account', 'wp-mail-smtp' ); ?>
|
121 |
+
</a>
|
122 |
+
<p class="desc">
|
123 |
+
<?php esc_html_e( 'Click the button above to confirm authorization.', 'wp-mail-smtp' ); ?>
|
124 |
+
</p>
|
125 |
+
</div>
|
126 |
+
</div>
|
127 |
+
<?php endif; ?>
|
128 |
+
|
129 |
+
<?php
|
130 |
+
}
|
131 |
+
}
|
src/Providers/Loader.php
CHANGED
@@ -1,178 +1,178 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Providers;
|
4 |
-
|
5 |
-
use WPMailSMTP\MailCatcher;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Class Loader.
|
9 |
-
*
|
10 |
-
* @since 1.0.0
|
11 |
-
*/
|
12 |
-
class Loader {
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Key is the mailer option, value is the path to its classes.
|
16 |
-
*
|
17 |
-
* @var array
|
18 |
-
*/
|
19 |
-
protected $providers = array(
|
20 |
-
'mail' => '\WPMailSMTP\Providers\Mail\\',
|
21 |
-
'gmail' => '\WPMailSMTP\Providers\Gmail\\',
|
22 |
-
'mailgun' => '\WPMailSMTP\Providers\Mailgun\\',
|
23 |
-
'sendgrid' => '\WPMailSMTP\Providers\Sendgrid\\',
|
24 |
-
'pepipost' => '\WPMailSMTP\Providers\Pepipost\\',
|
25 |
-
'smtp' => '\WPMailSMTP\Providers\SMTP\\',
|
26 |
-
);
|
27 |
-
|
28 |
-
/**
|
29 |
-
* @var \WPMailSMTP\MailCatcher
|
30 |
-
*/
|
31 |
-
private $phpmailer;
|
32 |
-
|
33 |
-
/**
|
34 |
-
* Get all the supported providers.
|
35 |
-
*
|
36 |
-
* @since 1.0.0
|
37 |
-
*
|
38 |
-
* @return array
|
39 |
-
*/
|
40 |
-
public function get_providers() {
|
41 |
-
return apply_filters( 'wp_mail_smtp_providers_loader_get_providers', $this->providers );
|
42 |
-
}
|
43 |
-
|
44 |
-
/**
|
45 |
-
* Get a single provider FQN-path based on its name.
|
46 |
-
*
|
47 |
-
* @since 1.0.0
|
48 |
-
*
|
49 |
-
* @param string $provider
|
50 |
-
*
|
51 |
-
* @return array
|
52 |
-
*/
|
53 |
-
public function get_provider_path( $provider ) {
|
54 |
-
$provider = sanitize_key( $provider );
|
55 |
-
|
56 |
-
return apply_filters(
|
57 |
-
'wp_mail_smtp_providers_loader_get_provider_path',
|
58 |
-
isset( $this->providers[ $provider ] ) ? $this->providers[ $provider ] : null,
|
59 |
-
$provider
|
60 |
-
);
|
61 |
-
}
|
62 |
-
|
63 |
-
/**
|
64 |
-
* Get the provider options, if exists.
|
65 |
-
*
|
66 |
-
* @since 1.0.0
|
67 |
-
*
|
68 |
-
* @param string $provider
|
69 |
-
*
|
70 |
-
* @return \WPMailSMTP\Providers\OptionAbstract|null
|
71 |
-
*/
|
72 |
-
public function get_options( $provider ) {
|
73 |
-
return $this->get_entity( $provider, 'Options' );
|
74 |
-
}
|
75 |
-
|
76 |
-
/**
|
77 |
-
* Get all options of all providers.
|
78 |
-
*
|
79 |
-
* @since 1.0.0
|
80 |
-
*
|
81 |
-
* @return \WPMailSMTP\Providers\OptionAbstract[]
|
82 |
-
*/
|
83 |
-
public function get_options_all() {
|
84 |
-
$options = array();
|
85 |
-
|
86 |
-
foreach ( $this->get_providers() as $provider => $path ) {
|
87 |
-
|
88 |
-
$option = $this->get_options( $provider );
|
89 |
-
|
90 |
-
if ( ! $option instanceof OptionAbstract ) {
|
91 |
-
continue;
|
92 |
-
}
|
93 |
-
|
94 |
-
$slug = $option->get_slug();
|
95 |
-
$title = $option->get_title();
|
96 |
-
|
97 |
-
if ( empty( $title ) || empty( $slug ) ) {
|
98 |
-
continue;
|
99 |
-
}
|
100 |
-
|
101 |
-
$options[] = $option;
|
102 |
-
}
|
103 |
-
|
104 |
-
return apply_filters( 'wp_mail_smtp_providers_loader_get_providers_all', $options );
|
105 |
-
}
|
106 |
-
|
107 |
-
/**
|
108 |
-
* Get the provider mailer, if exists.
|
109 |
-
*
|
110 |
-
* @since 1.0.0
|
111 |
-
*
|
112 |
-
* @param string $provider
|
113 |
-
* @param MailCatcher $phpmailer
|
114 |
-
*
|
115 |
-
* @return \WPMailSMTP\Providers\MailerAbstract|null
|
116 |
-
*/
|
117 |
-
public function get_mailer( $provider, $phpmailer ) {
|
118 |
-
|
119 |
-
if ( $phpmailer instanceof MailCatcher ) {
|
120 |
-
$this->phpmailer = $phpmailer;
|
121 |
-
}
|
122 |
-
|
123 |
-
return $this->get_entity( $provider, 'Mailer' );
|
124 |
-
}
|
125 |
-
|
126 |
-
/**
|
127 |
-
* Get the provider auth, if exists.
|
128 |
-
*
|
129 |
-
* @param string $provider
|
130 |
-
*
|
131 |
-
* @return \WPMailSMTP\Providers\AuthAbstract|null
|
132 |
-
*/
|
133 |
-
public function get_auth( $provider ) {
|
134 |
-
return $this->get_entity( $provider, 'Auth' );
|
135 |
-
}
|
136 |
-
|
137 |
-
/**
|
138 |
-
* Get a generic entity based on the request.
|
139 |
-
*
|
140 |
-
* @uses ReflectionClass
|
141 |
-
*
|
142 |
-
* @since 1.0.0
|
143 |
-
*
|
144 |
-
* @param string $provider
|
145 |
-
* @param string $request
|
146 |
-
*
|
147 |
-
* @return null
|
148 |
-
*/
|
149 |
-
protected function get_entity( $provider, $request ) {
|
150 |
-
|
151 |
-
$provider = sanitize_key( $provider );
|
152 |
-
$request = sanitize_text_field( $request );
|
153 |
-
$path = $this->get_provider_path( $provider );
|
154 |
-
$entity = null;
|
155 |
-
|
156 |
-
if ( empty( $path ) ) {
|
157 |
-
return $entity;
|
158 |
-
}
|
159 |
-
|
160 |
-
try {
|
161 |
-
$reflection = new \ReflectionClass( $path . $request );
|
162 |
-
|
163 |
-
if ( file_exists( $reflection->getFileName() ) ) {
|
164 |
-
$class = $path . $request;
|
165 |
-
if ( $this->phpmailer ) {
|
166 |
-
$entity = new $class( $this->phpmailer );
|
167 |
-
} else {
|
168 |
-
$entity = new $class();
|
169 |
-
}
|
170 |
-
}
|
171 |
-
} catch ( \Exception $e ) {
|
172 |
-
// TODO: save error message later to display a user.
|
173 |
-
$entity = null;
|
174 |
-
}
|
175 |
-
|
176 |
-
return apply_filters( 'wp_mail_smtp_providers_loader_get_entity', $entity, $provider, $request );
|
177 |
-
}
|
178 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Providers;
|
4 |
+
|
5 |
+
use WPMailSMTP\MailCatcher;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class Loader.
|
9 |
+
*
|
10 |
+
* @since 1.0.0
|
11 |
+
*/
|
12 |
+
class Loader {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Key is the mailer option, value is the path to its classes.
|
16 |
+
*
|
17 |
+
* @var array
|
18 |
+
*/
|
19 |
+
protected $providers = array(
|
20 |
+
'mail' => '\WPMailSMTP\Providers\Mail\\',
|
21 |
+
'gmail' => '\WPMailSMTP\Providers\Gmail\\',
|
22 |
+
'mailgun' => '\WPMailSMTP\Providers\Mailgun\\',
|
23 |
+
'sendgrid' => '\WPMailSMTP\Providers\Sendgrid\\',
|
24 |
+
'pepipost' => '\WPMailSMTP\Providers\Pepipost\\',
|
25 |
+
'smtp' => '\WPMailSMTP\Providers\SMTP\\',
|
26 |
+
);
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @var \WPMailSMTP\MailCatcher
|
30 |
+
*/
|
31 |
+
private $phpmailer;
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Get all the supported providers.
|
35 |
+
*
|
36 |
+
* @since 1.0.0
|
37 |
+
*
|
38 |
+
* @return array
|
39 |
+
*/
|
40 |
+
public function get_providers() {
|
41 |
+
return apply_filters( 'wp_mail_smtp_providers_loader_get_providers', $this->providers );
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Get a single provider FQN-path based on its name.
|
46 |
+
*
|
47 |
+
* @since 1.0.0
|
48 |
+
*
|
49 |
+
* @param string $provider
|
50 |
+
*
|
51 |
+
* @return array
|
52 |
+
*/
|
53 |
+
public function get_provider_path( $provider ) {
|
54 |
+
$provider = sanitize_key( $provider );
|
55 |
+
|
56 |
+
return apply_filters(
|
57 |
+
'wp_mail_smtp_providers_loader_get_provider_path',
|
58 |
+
isset( $this->providers[ $provider ] ) ? $this->providers[ $provider ] : null,
|
59 |
+
$provider
|
60 |
+
);
|
61 |
+
}
|
62 |
+
|
63 |
+
/**
|
64 |
+
* Get the provider options, if exists.
|
65 |
+
*
|
66 |
+
* @since 1.0.0
|
67 |
+
*
|
68 |
+
* @param string $provider
|
69 |
+
*
|
70 |
+
* @return \WPMailSMTP\Providers\OptionAbstract|null
|
71 |
+
*/
|
72 |
+
public function get_options( $provider ) {
|
73 |
+
return $this->get_entity( $provider, 'Options' );
|
74 |
+
}
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Get all options of all providers.
|
78 |
+
*
|
79 |
+
* @since 1.0.0
|
80 |
+
*
|
81 |
+
* @return \WPMailSMTP\Providers\OptionAbstract[]
|
82 |
+
*/
|
83 |
+
public function get_options_all() {
|
84 |
+
$options = array();
|
85 |
+
|
86 |
+
foreach ( $this->get_providers() as $provider => $path ) {
|
87 |
+
|
88 |
+
$option = $this->get_options( $provider );
|
89 |
+
|
90 |
+
if ( ! $option instanceof OptionAbstract ) {
|
91 |
+
continue;
|
92 |
+
}
|
93 |
+
|
94 |
+
$slug = $option->get_slug();
|
95 |
+
$title = $option->get_title();
|
96 |
+
|
97 |
+
if ( empty( $title ) || empty( $slug ) ) {
|
98 |
+
continue;
|
99 |
+
}
|
100 |
+
|
101 |
+
$options[] = $option;
|
102 |
+
}
|
103 |
+
|
104 |
+
return apply_filters( 'wp_mail_smtp_providers_loader_get_providers_all', $options );
|
105 |
+
}
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Get the provider mailer, if exists.
|
109 |
+
*
|
110 |
+
* @since 1.0.0
|
111 |
+
*
|
112 |
+
* @param string $provider
|
113 |
+
* @param MailCatcher $phpmailer
|
114 |
+
*
|
115 |
+
* @return \WPMailSMTP\Providers\MailerAbstract|null
|
116 |
+
*/
|
117 |
+
public function get_mailer( $provider, $phpmailer ) {
|
118 |
+
|
119 |
+
if ( $phpmailer instanceof MailCatcher ) {
|
120 |
+
$this->phpmailer = $phpmailer;
|
121 |
+
}
|
122 |
+
|
123 |
+
return $this->get_entity( $provider, 'Mailer' );
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Get the provider auth, if exists.
|
128 |
+
*
|
129 |
+
* @param string $provider
|
130 |
+
*
|
131 |
+
* @return \WPMailSMTP\Providers\AuthAbstract|null
|
132 |
+
*/
|
133 |
+
public function get_auth( $provider ) {
|
134 |
+
return $this->get_entity( $provider, 'Auth' );
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Get a generic entity based on the request.
|
139 |
+
*
|
140 |
+
* @uses ReflectionClass
|
141 |
+
*
|
142 |
+
* @since 1.0.0
|
143 |
+
*
|
144 |
+
* @param string $provider
|
145 |
+
* @param string $request
|
146 |
+
*
|
147 |
+
* @return null
|
148 |
+
*/
|
149 |
+
protected function get_entity( $provider, $request ) {
|
150 |
+
|
151 |
+
$provider = sanitize_key( $provider );
|
152 |
+
$request = sanitize_text_field( $request );
|
153 |
+
$path = $this->get_provider_path( $provider );
|
154 |
+
$entity = null;
|
155 |
+
|
156 |
+
if ( empty( $path ) ) {
|
157 |
+
return $entity;
|
158 |
+
}
|
159 |
+
|
160 |
+
try {
|
161 |
+
$reflection = new \ReflectionClass( $path . $request );
|
162 |
+
|
163 |
+
if ( file_exists( $reflection->getFileName() ) ) {
|
164 |
+
$class = $path . $request;
|
165 |
+
if ( $this->phpmailer ) {
|
166 |
+
$entity = new $class( $this->phpmailer );
|
167 |
+
} else {
|
168 |
+
$entity = new $class();
|
169 |
+
}
|
170 |
+
}
|
171 |
+
} catch ( \Exception $e ) {
|
172 |
+
// TODO: save error message later to display a user.
|
173 |
+
$entity = null;
|
174 |
+
}
|
175 |
+
|
176 |
+
return apply_filters( 'wp_mail_smtp_providers_loader_get_entity', $entity, $provider, $request );
|
177 |
+
}
|
178 |
+
}
|
src/Providers/Mail/Options.php
CHANGED
@@ -1,42 +1,42 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Providers\Mail;
|
4 |
-
|
5 |
-
use WPMailSMTP\Providers\OptionAbstract;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Class Option.
|
9 |
-
*
|
10 |
-
* @since 1.0.0
|
11 |
-
*/
|
12 |
-
class Options extends OptionAbstract {
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Mail constructor.
|
16 |
-
*
|
17 |
-
* @since 1.0.0
|
18 |
-
*/
|
19 |
-
public function __construct() {
|
20 |
-
|
21 |
-
parent::__construct(
|
22 |
-
array(
|
23 |
-
'logo_url' => wp_mail_smtp()->plugin_url . '/assets/images/php.png',
|
24 |
-
'slug' => 'mail',
|
25 |
-
'title' => esc_html__( 'Default (none)', 'wp-mail-smtp' ),
|
26 |
-
)
|
27 |
-
);
|
28 |
-
}
|
29 |
-
|
30 |
-
/**
|
31 |
-
* @inheritdoc
|
32 |
-
*/
|
33 |
-
public function display_options() {
|
34 |
-
?>
|
35 |
-
|
36 |
-
<blockquote>
|
37 |
-
<?php esc_html_e( 'You currently have the native WordPress option selected. Please select any other Mailer option above to continue the setup.', 'wp-mail-smtp' ); ?>
|
38 |
-
</blockquote>
|
39 |
-
|
40 |
-
<?php
|
41 |
-
}
|
42 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Providers\Mail;
|
4 |
+
|
5 |
+
use WPMailSMTP\Providers\OptionAbstract;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class Option.
|
9 |
+
*
|
10 |
+
* @since 1.0.0
|
11 |
+
*/
|
12 |
+
class Options extends OptionAbstract {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Mail constructor.
|
16 |
+
*
|
17 |
+
* @since 1.0.0
|
18 |
+
*/
|
19 |
+
public function __construct() {
|
20 |
+
|
21 |
+
parent::__construct(
|
22 |
+
array(
|
23 |
+
'logo_url' => wp_mail_smtp()->plugin_url . '/assets/images/php.png',
|
24 |
+
'slug' => 'mail',
|
25 |
+
'title' => esc_html__( 'Default (none)', 'wp-mail-smtp' ),
|
26 |
+
)
|
27 |
+
);
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* @inheritdoc
|
32 |
+
*/
|
33 |
+
public function display_options() {
|
34 |
+
?>
|
35 |
+
|
36 |
+
<blockquote>
|
37 |
+
<?php esc_html_e( 'You currently have the native WordPress option selected. Please select any other Mailer option above to continue the setup.', 'wp-mail-smtp' ); ?>
|
38 |
+
</blockquote>
|
39 |
+
|
40 |
+
<?php
|
41 |
+
}
|
42 |
+
}
|
src/Providers/MailerAbstract.php
CHANGED
@@ -1,346 +1,346 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Providers;
|
4 |
-
|
5 |
-
use WPMailSMTP\MailCatcher;
|
6 |
-
use WPMailSMTP\Options;
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Class MailerAbstract.
|
10 |
-
*
|
11 |
-
* @since 1.0.0
|
12 |
-
*/
|
13 |
-
abstract class MailerAbstract implements MailerInterface {
|
14 |
-
|
15 |
-
/**
|
16 |
-
* Which response code from HTTP provider is considered to be successful?
|
17 |
-
*
|
18 |
-
* @var int
|
19 |
-
*/
|
20 |
-
protected $email_sent_code = 200;
|
21 |
-
/**
|
22 |
-
* @var Options
|
23 |
-
*/
|
24 |
-
protected $options;
|
25 |
-
/**
|
26 |
-
* @var MailCatcher
|
27 |
-
*/
|
28 |
-
protected $phpmailer;
|
29 |
-
/**
|
30 |
-
* @var string
|
31 |
-
*/
|
32 |
-
protected $mailer = '';
|
33 |
-
|
34 |
-
/**
|
35 |
-
* URL to make an API request to.
|
36 |
-
*
|
37 |
-
* @var string
|
38 |
-
*/
|
39 |
-
protected $url = '';
|
40 |
-
/**
|
41 |
-
* @var array
|
42 |
-
*/
|
43 |
-
protected $headers = array();
|
44 |
-
/**
|
45 |
-
* @var array
|
46 |
-
*/
|
47 |
-
protected $body = array();
|
48 |
-
/**
|
49 |
-
* @var mixed
|
50 |
-
*/
|
51 |
-
protected $response = array();
|
52 |
-
|
53 |
-
/**
|
54 |
-
* Mailer constructor.
|
55 |
-
*
|
56 |
-
* @since 1.0.0
|
57 |
-
*
|
58 |
-
* @param MailCatcher $phpmailer
|
59 |
-
*/
|
60 |
-
public function __construct( MailCatcher $phpmailer ) {
|
61 |
-
|
62 |
-
if ( empty( $this->url ) ) {
|
63 |
-
return;
|
64 |
-
}
|
65 |
-
|
66 |
-
$this->options = new Options();
|
67 |
-
$this->mailer = $this->options->get( 'mail', 'mailer' );
|
68 |
-
|
69 |
-
$this->process_phpmailer( $phpmailer );
|
70 |
-
}
|
71 |
-
|
72 |
-
/**
|
73 |
-
* Re-use the MailCatcher class methods and properties.
|
74 |
-
*
|
75 |
-
* @since 1.0.0
|
76 |
-
*
|
77 |
-
* @param MailCatcher $phpmailer
|
78 |
-
*/
|
79 |
-
protected function process_phpmailer( $phpmailer ) {
|
80 |
-
|
81 |
-
// Make sure that we have access to PHPMailer class methods.
|
82 |
-
if ( ! $phpmailer instanceof MailCatcher ) {
|
83 |
-
return;
|
84 |
-
}
|
85 |
-
|
86 |
-
$this->phpmailer = $phpmailer;
|
87 |
-
|
88 |
-
$this->set_headers( $this->phpmailer->getCustomHeaders() );
|
89 |
-
$this->set_from( $this->phpmailer->From, $this->phpmailer->FromName );
|
90 |
-
$this->set_recipients(
|
91 |
-
array(
|
92 |
-
'to' => $this->phpmailer->getToAddresses(),
|
93 |
-
'cc' => $this->phpmailer->getCcAddresses(),
|
94 |
-
'bcc' => $this->phpmailer->getBccAddresses(),
|
95 |
-
)
|
96 |
-
);
|
97 |
-
$this->set_subject( $this->phpmailer->Subject );
|
98 |
-
$this->set_content(
|
99 |
-
array(
|
100 |
-
'html' => $this->phpmailer->Body,
|
101 |
-
'text' => $this->phpmailer->AltBody,
|
102 |
-
)
|
103 |
-
);
|
104 |
-
$this->set_return_path( $this->phpmailer->From );
|
105 |
-
$this->set_reply_to( $this->phpmailer->getReplyToAddresses() );
|
106 |
-
|
107 |
-
/*
|
108 |
-
* In some cases we will need to modify the internal structure
|
109 |
-
* of the body content, if attachments are present.
|
110 |
-
* So lets make this call the last one.
|
111 |
-
*/
|
112 |
-
$this->set_attachments( $this->phpmailer->getAttachments() );
|
113 |
-
}
|
114 |
-
|
115 |
-
/**
|
116 |
-
* @inheritdoc
|
117 |
-
*/
|
118 |
-
public function set_subject( $subject ) {
|
119 |
-
|
120 |
-
$this->set_body_param(
|
121 |
-
array(
|
122 |
-
'subject' => $subject,
|
123 |
-
)
|
124 |
-
);
|
125 |
-
}
|
126 |
-
|
127 |
-
/**
|
128 |
-
* Set the request params, that goes to the body of the HTTP request.
|
129 |
-
*
|
130 |
-
* @since 1.0.0
|
131 |
-
*
|
132 |
-
* @param array $param Key=>value of what should be sent to a 3rd party API.
|
133 |
-
*
|
134 |
-
* @internal param array $params
|
135 |
-
*/
|
136 |
-
protected function set_body_param( $param ) {
|
137 |
-
$this->body = $this->array_merge_recursive( $this->body, $param );
|
138 |
-
}
|
139 |
-
|
140 |
-
/**
|
141 |
-
* @inheritdoc
|
142 |
-
*/
|
143 |
-
public function set_headers( $headers ) {
|
144 |
-
|
145 |
-
foreach ( $headers as $header ) {
|
146 |
-
$name = isset( $header[0] ) ? $header[0] : false;
|
147 |
-
$value = isset( $header[1] ) ? $header[1] : false;
|
148 |
-
|
149 |
-
if ( empty( $name ) || empty( $value ) ) {
|
150 |
-
continue;
|
151 |
-
}
|
152 |
-
|
153 |
-
$this->set_header( $name, $value );
|
154 |
-
}
|
155 |
-
}
|
156 |
-
|
157 |
-
/**
|
158 |
-
* @inheritdoc
|
159 |
-
*/
|
160 |
-
public function set_header( $name, $value ) {
|
161 |
-
|
162 |
-
$process_value = function ( $value ) {
|
163 |
-
// Remove HTML tags.
|
164 |
-
$filtered = wp_strip_all_tags( $value, false );
|
165 |
-
// Remove multi-lines/tabs.
|
166 |
-
$filtered = preg_replace( '/[\r\n\t ]+/', ' ', $filtered );
|
167 |
-
// Remove whitespaces.
|
168 |
-
$filtered = trim( $filtered );
|
169 |
-
|
170 |
-
// Remove octets.
|
171 |
-
$found = false;
|
172 |
-
while ( preg_match( '/%[a-f0-9]{2}/i', $filtered, $match ) ) {
|
173 |
-
$filtered = str_replace( $match[0], '', $filtered );
|
174 |
-
$found = true;
|
175 |
-
}
|
176 |
-
|
177 |
-
if ( $found ) {
|
178 |
-
// Strip out the whitespace that may now exist after removing the octets.
|
179 |
-
$filtered = trim( preg_replace( '/ +/', ' ', $filtered ) );
|
180 |
-
}
|
181 |
-
|
182 |
-
return $filtered;
|
183 |
-
};
|
184 |
-
|
185 |
-
$name = sanitize_text_field( $name );
|
186 |
-
if ( empty( $name ) ) {
|
187 |
-
return;
|
188 |
-
}
|
189 |
-
|
190 |
-
$value = $process_value( $value );
|
191 |
-
|
192 |
-
$this->headers[ $name ] = $value;
|
193 |
-
}
|
194 |
-
|
195 |
-
/**
|
196 |
-
* @inheritdoc
|
197 |
-
*/
|
198 |
-
public function get_body() {
|
199 |
-
return apply_filters( 'wp_mail_smtp_providers_mailer_get_body', $this->body );
|
200 |
-
}
|
201 |
-
|
202 |
-
/**
|
203 |
-
* @inheritdoc
|
204 |
-
*/
|
205 |
-
public function get_headers() {
|
206 |
-
return apply_filters( 'wp_mail_smtp_providers_mailer_get_headers', $this->headers );
|
207 |
-
}
|
208 |
-
|
209 |
-
/**
|
210 |
-
* @inheritdoc
|
211 |
-
*/
|
212 |
-
public function send() {
|
213 |
-
|
214 |
-
$params = $this->array_merge_recursive( $this->get_default_params(), array(
|
215 |
-
'headers' => $this->get_headers(),
|
216 |
-
'body' => $this->get_body(),
|
217 |
-
) );
|
218 |
-
|
219 |
-
$response = wp_safe_remote_post( $this->url, $params );
|
220 |
-
|
221 |
-
$this->process_response( $response );
|
222 |
-
}
|
223 |
-
|
224 |
-
/**
|
225 |
-
* We might need to do something after the email was sent to the API.
|
226 |
-
* In this method we preprocess the response from the API.
|
227 |
-
*
|
228 |
-
* @since 1.0.0
|
229 |
-
*
|
230 |
-
* @param array|\WP_Error $response
|
231 |
-
*/
|
232 |
-
protected function process_response( $response ) {
|
233 |
-
|
234 |
-
if ( is_wp_error( $response ) ) {
|
235 |
-
return;
|
236 |
-
}
|
237 |
-
|
238 |
-
if ( isset( $response['body'] ) && $this->is_json( $response['body'] ) ) {
|
239 |
-
$response['body'] = json_decode( $response['body'] );
|
240 |
-
}
|
241 |
-
|
242 |
-
$this->response = $response;
|
243 |
-
}
|
244 |
-
|
245 |
-
/**
|
246 |
-
* Get the default params, required for wp_safe_remote_post().
|
247 |
-
*
|
248 |
-
* @since 1.0.0
|
249 |
-
*
|
250 |
-
* @return array
|
251 |
-
*/
|
252 |
-
protected function get_default_params() {
|
253 |
-
|
254 |
-
return apply_filters( 'wp_mail_smtp_providers_mailer_get_default_params', array(
|
255 |
-
'timeout' => 15,
|
256 |
-
'httpversion' => '1.1',
|
257 |
-
'blocking' => true,
|
258 |
-
) );
|
259 |
-
}
|
260 |
-
|
261 |
-
/**
|
262 |
-
* @inheritdoc
|
263 |
-
*/
|
264 |
-
public function is_email_sent() {
|
265 |
-
|
266 |
-
$is_sent = false;
|
267 |
-
|
268 |
-
if ( wp_remote_retrieve_response_code( $this->response ) === $this->email_sent_code ) {
|
269 |
-
$is_sent = true;
|
270 |
-
}
|
271 |
-
|
272 |
-
return apply_filters( 'wp_mail_smtp_providers_mailer_is_email_sent', $is_sent );
|
273 |
-
}
|
274 |
-
|
275 |
-
/**
|
276 |
-
* @inheritdoc
|
277 |
-
*/
|
278 |
-
public function is_php_compatible() {
|
279 |
-
|
280 |
-
$options = wp_mail_smtp()->get_providers()->get_options( $this->mailer );
|
281 |
-
|
282 |
-
return version_compare( phpversion(), $options->get_php_version(), '>=' );
|
283 |
-
}
|
284 |
-
|
285 |
-
/**
|
286 |
-
* Check whether the string is a JSON or not.
|
287 |
-
*
|
288 |
-
* @since 1.0.0
|
289 |
-
*
|
290 |
-
* @param string $string
|
291 |
-
*
|
292 |
-
* @return bool
|
293 |
-
*/
|
294 |
-
protected function is_json( $string ) {
|
295 |
-
return is_string( $string ) && is_array( json_decode( $string, true ) ) && ( json_last_error() === JSON_ERROR_NONE ) ? true : false;
|
296 |
-
}
|
297 |
-
|
298 |
-
/**
|
299 |
-
* Merge recursively, including a proper substitution of values in sub-arrays when keys are the same.
|
300 |
-
* It's more like array_merge() and array_merge_recursive() combined.
|
301 |
-
*
|
302 |
-
* @since 1.0.0
|
303 |
-
*
|
304 |
-
* @return array
|
305 |
-
*/
|
306 |
-
protected function array_merge_recursive() {
|
307 |
-
|
308 |
-
$arrays = func_get_args();
|
309 |
-
|
310 |
-
if ( count( $arrays ) < 2 ) {
|
311 |
-
return isset( $arrays[0] ) ? $arrays[0] : array();
|
312 |
-
}
|
313 |
-
|
314 |
-
$merged = array();
|
315 |
-
|
316 |
-
while ( $arrays ) {
|
317 |
-
$array = array_shift( $arrays );
|
318 |
-
|
319 |
-
if ( ! is_array( $array ) ) {
|
320 |
-
return array();
|
321 |
-
}
|
322 |
-
|
323 |
-
if ( empty( $array ) ) {
|
324 |
-
continue;
|
325 |
-
}
|
326 |
-
|
327 |
-
foreach ( $array as $key => $value ) {
|
328 |
-
if ( is_string( $key ) ) {
|
329 |
-
if (
|
330 |
-
is_array( $value ) &&
|
331 |
-
array_key_exists( $key, $merged ) &&
|
332 |
-
is_array( $merged[ $key ] )
|
333 |
-
) {
|
334 |
-
$merged[ $key ] = call_user_func( __FUNCTION__, $merged[ $key ], $value );
|
335 |
-
} else {
|
336 |
-
$merged[ $key ] = $value;
|
337 |
-
}
|
338 |
-
} else {
|
339 |
-
$merged[] = $value;
|
340 |
-
}
|
341 |
-
}
|
342 |
-
}
|
343 |
-
|
344 |
-
return $merged;
|
345 |
-
}
|
346 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Providers;
|
4 |
+
|
5 |
+
use WPMailSMTP\MailCatcher;
|
6 |
+
use WPMailSMTP\Options;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class MailerAbstract.
|
10 |
+
*
|
11 |
+
* @since 1.0.0
|
12 |
+
*/
|
13 |
+
abstract class MailerAbstract implements MailerInterface {
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Which response code from HTTP provider is considered to be successful?
|
17 |
+
*
|
18 |
+
* @var int
|
19 |
+
*/
|
20 |
+
protected $email_sent_code = 200;
|
21 |
+
/**
|
22 |
+
* @var Options
|
23 |
+
*/
|
24 |
+
protected $options;
|
25 |
+
/**
|
26 |
+
* @var MailCatcher
|
27 |
+
*/
|
28 |
+
protected $phpmailer;
|
29 |
+
/**
|
30 |
+
* @var string
|
31 |
+
*/
|
32 |
+
protected $mailer = '';
|
33 |
+
|
34 |
+
/**
|
35 |
+
* URL to make an API request to.
|
36 |
+
*
|
37 |
+
* @var string
|
38 |
+
*/
|
39 |
+
protected $url = '';
|
40 |
+
/**
|
41 |
+
* @var array
|
42 |
+
*/
|
43 |
+
protected $headers = array();
|
44 |
+
/**
|
45 |
+
* @var array
|
46 |
+
*/
|
47 |
+
protected $body = array();
|
48 |
+
/**
|
49 |
+
* @var mixed
|
50 |
+
*/
|
51 |
+
protected $response = array();
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Mailer constructor.
|
55 |
+
*
|
56 |
+
* @since 1.0.0
|
57 |
+
*
|
58 |
+
* @param MailCatcher $phpmailer
|
59 |
+
*/
|
60 |
+
public function __construct( MailCatcher $phpmailer ) {
|
61 |
+
|
62 |
+
if ( empty( $this->url ) ) {
|
63 |
+
return;
|
64 |
+
}
|
65 |
+
|
66 |
+
$this->options = new Options();
|
67 |
+
$this->mailer = $this->options->get( 'mail', 'mailer' );
|
68 |
+
|
69 |
+
$this->process_phpmailer( $phpmailer );
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Re-use the MailCatcher class methods and properties.
|
74 |
+
*
|
75 |
+
* @since 1.0.0
|
76 |
+
*
|
77 |
+
* @param MailCatcher $phpmailer
|
78 |
+
*/
|
79 |
+
protected function process_phpmailer( $phpmailer ) {
|
80 |
+
|
81 |
+
// Make sure that we have access to PHPMailer class methods.
|
82 |
+
if ( ! $phpmailer instanceof MailCatcher ) {
|
83 |
+
return;
|
84 |
+
}
|
85 |
+
|
86 |
+
$this->phpmailer = $phpmailer;
|
87 |
+
|
88 |
+
$this->set_headers( $this->phpmailer->getCustomHeaders() );
|
89 |
+
$this->set_from( $this->phpmailer->From, $this->phpmailer->FromName );
|
90 |
+
$this->set_recipients(
|
91 |
+
array(
|
92 |
+
'to' => $this->phpmailer->getToAddresses(),
|
93 |
+
'cc' => $this->phpmailer->getCcAddresses(),
|
94 |
+
'bcc' => $this->phpmailer->getBccAddresses(),
|
95 |
+
)
|
96 |
+
);
|
97 |
+
$this->set_subject( $this->phpmailer->Subject );
|
98 |
+
$this->set_content(
|
99 |
+
array(
|
100 |
+
'html' => $this->phpmailer->Body,
|
101 |
+
'text' => $this->phpmailer->AltBody,
|
102 |
+
)
|
103 |
+
);
|
104 |
+
$this->set_return_path( $this->phpmailer->From );
|
105 |
+
$this->set_reply_to( $this->phpmailer->getReplyToAddresses() );
|
106 |
+
|
107 |
+
/*
|
108 |
+
* In some cases we will need to modify the internal structure
|
109 |
+
* of the body content, if attachments are present.
|
110 |
+
* So lets make this call the last one.
|
111 |
+
*/
|
112 |
+
$this->set_attachments( $this->phpmailer->getAttachments() );
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* @inheritdoc
|
117 |
+
*/
|
118 |
+
public function set_subject( $subject ) {
|
119 |
+
|
120 |
+
$this->set_body_param(
|
121 |
+
array(
|
122 |
+
'subject' => $subject,
|
123 |
+
)
|
124 |
+
);
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Set the request params, that goes to the body of the HTTP request.
|
129 |
+
*
|
130 |
+
* @since 1.0.0
|
131 |
+
*
|
132 |
+
* @param array $param Key=>value of what should be sent to a 3rd party API.
|
133 |
+
*
|
134 |
+
* @internal param array $params
|
135 |
+
*/
|
136 |
+
protected function set_body_param( $param ) {
|
137 |
+
$this->body = $this->array_merge_recursive( $this->body, $param );
|
138 |
+
}
|
139 |
+
|
140 |
+
/**
|
141 |
+
* @inheritdoc
|
142 |
+
*/
|
143 |
+
public function set_headers( $headers ) {
|
144 |
+
|
145 |
+
foreach ( $headers as $header ) {
|
146 |
+
$name = isset( $header[0] ) ? $header[0] : false;
|
147 |
+
$value = isset( $header[1] ) ? $header[1] : false;
|
148 |
+
|
149 |
+
if ( empty( $name ) || empty( $value ) ) {
|
150 |
+
continue;
|
151 |
+
}
|
152 |
+
|
153 |
+
$this->set_header( $name, $value );
|
154 |
+
}
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* @inheritdoc
|
159 |
+
*/
|
160 |
+
public function set_header( $name, $value ) {
|
161 |
+
|
162 |
+
$process_value = function ( $value ) {
|
163 |
+
// Remove HTML tags.
|
164 |
+
$filtered = wp_strip_all_tags( $value, false );
|
165 |
+
// Remove multi-lines/tabs.
|
166 |
+
$filtered = preg_replace( '/[\r\n\t ]+/', ' ', $filtered );
|
167 |
+
// Remove whitespaces.
|
168 |
+
$filtered = trim( $filtered );
|
169 |
+
|
170 |
+
// Remove octets.
|
171 |
+
$found = false;
|
172 |
+
while ( preg_match( '/%[a-f0-9]{2}/i', $filtered, $match ) ) {
|
173 |
+
$filtered = str_replace( $match[0], '', $filtered );
|
174 |
+
$found = true;
|
175 |
+
}
|
176 |
+
|
177 |
+
if ( $found ) {
|
178 |
+
// Strip out the whitespace that may now exist after removing the octets.
|
179 |
+
$filtered = trim( preg_replace( '/ +/', ' ', $filtered ) );
|
180 |
+
}
|
181 |
+
|
182 |
+
return $filtered;
|
183 |
+
};
|
184 |
+
|
185 |
+
$name = sanitize_text_field( $name );
|
186 |
+
if ( empty( $name ) ) {
|
187 |
+
return;
|
188 |
+
}
|
189 |
+
|
190 |
+
$value = $process_value( $value );
|
191 |
+
|
192 |
+
$this->headers[ $name ] = $value;
|
193 |
+
}
|
194 |
+
|
195 |
+
/**
|
196 |
+
* @inheritdoc
|
197 |
+
*/
|
198 |
+
public function get_body() {
|
199 |
+
return apply_filters( 'wp_mail_smtp_providers_mailer_get_body', $this->body );
|
200 |
+
}
|
201 |
+
|
202 |
+
/**
|
203 |
+
* @inheritdoc
|
204 |
+
*/
|
205 |
+
public function get_headers() {
|
206 |
+
return apply_filters( 'wp_mail_smtp_providers_mailer_get_headers', $this->headers );
|
207 |
+
}
|
208 |
+
|
209 |
+
/**
|
210 |
+
* @inheritdoc
|
211 |
+
*/
|
212 |
+
public function send() {
|
213 |
+
|
214 |
+
$params = $this->array_merge_recursive( $this->get_default_params(), array(
|
215 |
+
'headers' => $this->get_headers(),
|
216 |
+
'body' => $this->get_body(),
|
217 |
+
) );
|
218 |
+
|
219 |
+
$response = wp_safe_remote_post( $this->url, $params );
|
220 |
+
|
221 |
+
$this->process_response( $response );
|
222 |
+
}
|
223 |
+
|
224 |
+
/**
|
225 |
+
* We might need to do something after the email was sent to the API.
|
226 |
+
* In this method we preprocess the response from the API.
|
227 |
+
*
|
228 |
+
* @since 1.0.0
|
229 |
+
*
|
230 |
+
* @param array|\WP_Error $response
|
231 |
+
*/
|
232 |
+
protected function process_response( $response ) {
|
233 |
+
|
234 |
+
if ( is_wp_error( $response ) ) {
|
235 |
+
return;
|
236 |
+
}
|
237 |
+
|
238 |
+
if ( isset( $response['body'] ) && $this->is_json( $response['body'] ) ) {
|
239 |
+
$response['body'] = json_decode( $response['body'] );
|
240 |
+
}
|
241 |
+
|
242 |
+
$this->response = $response;
|
243 |
+
}
|
244 |
+
|
245 |
+
/**
|
246 |
+
* Get the default params, required for wp_safe_remote_post().
|
247 |
+
*
|
248 |
+
* @since 1.0.0
|
249 |
+
*
|
250 |
+
* @return array
|
251 |
+
*/
|
252 |
+
protected function get_default_params() {
|
253 |
+
|
254 |
+
return apply_filters( 'wp_mail_smtp_providers_mailer_get_default_params', array(
|
255 |
+
'timeout' => 15,
|
256 |
+
'httpversion' => '1.1',
|
257 |
+
'blocking' => true,
|
258 |
+
) );
|
259 |
+
}
|
260 |
+
|
261 |
+
/**
|
262 |
+
* @inheritdoc
|
263 |
+
*/
|
264 |
+
public function is_email_sent() {
|
265 |
+
|
266 |
+
$is_sent = false;
|
267 |
+
|
268 |
+
if ( wp_remote_retrieve_response_code( $this->response ) === $this->email_sent_code ) {
|
269 |
+
$is_sent = true;
|
270 |
+
}
|
271 |
+
|
272 |
+
return apply_filters( 'wp_mail_smtp_providers_mailer_is_email_sent', $is_sent );
|
273 |
+
}
|
274 |
+
|
275 |
+
/**
|
276 |
+
* @inheritdoc
|
277 |
+
*/
|
278 |
+
public function is_php_compatible() {
|
279 |
+
|
280 |
+
$options = wp_mail_smtp()->get_providers()->get_options( $this->mailer );
|
281 |
+
|
282 |
+
return version_compare( phpversion(), $options->get_php_version(), '>=' );
|
283 |
+
}
|
284 |
+
|
285 |
+
/**
|
286 |
+
* Check whether the string is a JSON or not.
|
287 |
+
*
|
288 |
+
* @since 1.0.0
|
289 |
+
*
|
290 |
+
* @param string $string
|
291 |
+
*
|
292 |
+
* @return bool
|
293 |
+
*/
|
294 |
+
protected function is_json( $string ) {
|
295 |
+
return is_string( $string ) && is_array( json_decode( $string, true ) ) && ( json_last_error() === JSON_ERROR_NONE ) ? true : false;
|
296 |
+
}
|
297 |
+
|
298 |
+
/**
|
299 |
+
* Merge recursively, including a proper substitution of values in sub-arrays when keys are the same.
|
300 |
+
* It's more like array_merge() and array_merge_recursive() combined.
|
301 |
+
*
|
302 |
+
* @since 1.0.0
|
303 |
+
*
|
304 |
+
* @return array
|
305 |
+
*/
|
306 |
+
protected function array_merge_recursive() {
|
307 |
+
|
308 |
+
$arrays = func_get_args();
|
309 |
+
|
310 |
+
if ( count( $arrays ) < 2 ) {
|
311 |
+
return isset( $arrays[0] ) ? $arrays[0] : array();
|
312 |
+
}
|
313 |
+
|
314 |
+
$merged = array();
|
315 |
+
|
316 |
+
while ( $arrays ) {
|
317 |
+
$array = array_shift( $arrays );
|
318 |
+
|
319 |
+
if ( ! is_array( $array ) ) {
|
320 |
+
return array();
|
321 |
+
}
|
322 |
+
|
323 |
+
if ( empty( $array ) ) {
|
324 |
+
continue;
|
325 |
+
}
|
326 |
+
|
327 |
+
foreach ( $array as $key => $value ) {
|
328 |
+
if ( is_string( $key ) ) {
|
329 |
+
if (
|
330 |
+
is_array( $value ) &&
|
331 |
+
array_key_exists( $key, $merged ) &&
|
332 |
+
is_array( $merged[ $key ] )
|
333 |
+
) {
|
334 |
+
$merged[ $key ] = call_user_func( __FUNCTION__, $merged[ $key ], $value );
|
335 |
+
} else {
|
336 |
+
$merged[ $key ] = $value;
|
337 |
+
}
|
338 |
+
} else {
|
339 |
+
$merged[] = $value;
|
340 |
+
}
|
341 |
+
}
|
342 |
+
}
|
343 |
+
|
344 |
+
return $merged;
|
345 |
+
}
|
346 |
+
}
|
src/Providers/MailerInterface.php
CHANGED
@@ -1,139 +1,139 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Providers;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Interface MailerInterface.
|
7 |
-
*
|
8 |
-
* @since 1.0.0
|
9 |
-
*/
|
10 |
-
interface MailerInterface {
|
11 |
-
|
12 |
-
/**
|
13 |
-
* Send the email.
|
14 |
-
*
|
15 |
-
* @since 1.0.0
|
16 |
-
*/
|
17 |
-
public function send();
|
18 |
-
|
19 |
-
/**
|
20 |
-
* Whether the email is sent or not.
|
21 |
-
* We basically check the response code from a request to provider.
|
22 |
-
* Might not be 100% correct, not guarantees that email is delivered.
|
23 |
-
*
|
24 |
-
* @since 1.0.0
|
25 |
-
*
|
26 |
-
* @return bool
|
27 |
-
*/
|
28 |
-
public function is_email_sent();
|
29 |
-
|
30 |
-
/**
|
31 |
-
* Whether the mailer supports the current PHP version or not.
|
32 |
-
*
|
33 |
-
* @since 1.0.0
|
34 |
-
*
|
35 |
-
* @return bool
|
36 |
-
*/
|
37 |
-
public function is_php_compatible();
|
38 |
-
|
39 |
-
/**
|
40 |
-
* Set the email headers in bulk.
|
41 |
-
*
|
42 |
-
* @since 1.0.0
|
43 |
-
*
|
44 |
-
* @param array $headers
|
45 |
-
*/
|
46 |
-
public function set_headers( $headers );
|
47 |
-
|
48 |
-
/**
|
49 |
-
* Set the email single header.
|
50 |
-
*
|
51 |
-
* @since 1.0.0
|
52 |
-
*
|
53 |
-
* @param string $name
|
54 |
-
* @param string $value
|
55 |
-
*/
|
56 |
-
public function set_header( $name, $value );
|
57 |
-
|
58 |
-
/**
|
59 |
-
* Set email FROM.
|
60 |
-
*
|
61 |
-
* @since 1.0.0
|
62 |
-
*
|
63 |
-
* @param string $email
|
64 |
-
* @param string $name
|
65 |
-
*/
|
66 |
-
public function set_from( $email, $name );
|
67 |
-
|
68 |
-
/**
|
69 |
-
* Set a bunch of email recipients: to, cc, bcc.
|
70 |
-
*
|
71 |
-
* @since 1.0.0
|
72 |
-
*
|
73 |
-
* @param array $recipients
|
74 |
-
*/
|
75 |
-
public function set_recipients( $recipients );
|
76 |
-
|
77 |
-
/**
|
78 |
-
* Set the email subject.
|
79 |
-
*
|
80 |
-
* @since 1.0.0
|
81 |
-
*
|
82 |
-
* @param string $subject
|
83 |
-
*/
|
84 |
-
public function set_subject( $subject );
|
85 |
-
|
86 |
-
/**
|
87 |
-
* Set the email content.
|
88 |
-
*
|
89 |
-
* @since 1.0.0
|
90 |
-
*
|
91 |
-
* @param string|array $content
|
92 |
-
*/
|
93 |
-
public function set_content( $content );
|
94 |
-
|
95 |
-
/**
|
96 |
-
* Set the email attachments.
|
97 |
-
*
|
98 |
-
* @since 1.0.0
|
99 |
-
*
|
100 |
-
* @param array $attachments
|
101 |
-
*/
|
102 |
-
public function set_attachments( $attachments );
|
103 |
-
|
104 |
-
/**
|
105 |
-
* Set the email reply_to option.
|
106 |
-
*
|
107 |
-
* @since 1.0.0
|
108 |
-
*
|
109 |
-
* @param array $reply_to
|
110 |
-
*/
|
111 |
-
public function set_reply_to( $reply_to );
|
112 |
-
|
113 |
-
/**
|
114 |
-
* Set the email return_path (when supported).
|
115 |
-
*
|
116 |
-
* @since 1.0.0
|
117 |
-
*
|
118 |
-
* @param string $email
|
119 |
-
*/
|
120 |
-
public function set_return_path( $email );
|
121 |
-
|
122 |
-
/**
|
123 |
-
* Get the email body.
|
124 |
-
*
|
125 |
-
* @since 1.0.0
|
126 |
-
*
|
127 |
-
* @return string|array
|
128 |
-
*/
|
129 |
-
public function get_body();
|
130 |
-
|
131 |
-
/**
|
132 |
-
* Get the email headers.
|
133 |
-
*
|
134 |
-
* @since 1.0.0
|
135 |
-
*
|
136 |
-
* @return array
|
137 |
-
*/
|
138 |
-
public function get_headers();
|
139 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Providers;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Interface MailerInterface.
|
7 |
+
*
|
8 |
+
* @since 1.0.0
|
9 |
+
*/
|
10 |
+
interface MailerInterface {
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Send the email.
|
14 |
+
*
|
15 |
+
* @since 1.0.0
|
16 |
+
*/
|
17 |
+
public function send();
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Whether the email is sent or not.
|
21 |
+
* We basically check the response code from a request to provider.
|
22 |
+
* Might not be 100% correct, not guarantees that email is delivered.
|
23 |
+
*
|
24 |
+
* @since 1.0.0
|
25 |
+
*
|
26 |
+
* @return bool
|
27 |
+
*/
|
28 |
+
public function is_email_sent();
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Whether the mailer supports the current PHP version or not.
|
32 |
+
*
|
33 |
+
* @since 1.0.0
|
34 |
+
*
|
35 |
+
* @return bool
|
36 |
+
*/
|
37 |
+
public function is_php_compatible();
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Set the email headers in bulk.
|
41 |
+
*
|
42 |
+
* @since 1.0.0
|
43 |
+
*
|
44 |
+
* @param array $headers
|
45 |
+
*/
|
46 |
+
public function set_headers( $headers );
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Set the email single header.
|
50 |
+
*
|
51 |
+
* @since 1.0.0
|
52 |
+
*
|
53 |
+
* @param string $name
|
54 |
+
* @param string $value
|
55 |
+
*/
|
56 |
+
public function set_header( $name, $value );
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Set email FROM.
|
60 |
+
*
|
61 |
+
* @since 1.0.0
|
62 |
+
*
|
63 |
+
* @param string $email
|
64 |
+
* @param string $name
|
65 |
+
*/
|
66 |
+
public function set_from( $email, $name );
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Set a bunch of email recipients: to, cc, bcc.
|
70 |
+
*
|
71 |
+
* @since 1.0.0
|
72 |
+
*
|
73 |
+
* @param array $recipients
|
74 |
+
*/
|
75 |
+
public function set_recipients( $recipients );
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Set the email subject.
|
79 |
+
*
|
80 |
+
* @since 1.0.0
|
81 |
+
*
|
82 |
+
* @param string $subject
|
83 |
+
*/
|
84 |
+
public function set_subject( $subject );
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Set the email content.
|
88 |
+
*
|
89 |
+
* @since 1.0.0
|
90 |
+
*
|
91 |
+
* @param string|array $content
|
92 |
+
*/
|
93 |
+
public function set_content( $content );
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Set the email attachments.
|
97 |
+
*
|
98 |
+
* @since 1.0.0
|
99 |
+
*
|
100 |
+
* @param array $attachments
|
101 |
+
*/
|
102 |
+
public function set_attachments( $attachments );
|
103 |
+
|
104 |
+
/**
|
105 |
+
* Set the email reply_to option.
|
106 |
+
*
|
107 |
+
* @since 1.0.0
|
108 |
+
*
|
109 |
+
* @param array $reply_to
|
110 |
+
*/
|
111 |
+
public function set_reply_to( $reply_to );
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Set the email return_path (when supported).
|
115 |
+
*
|
116 |
+
* @since 1.0.0
|
117 |
+
*
|
118 |
+
* @param string $email
|
119 |
+
*/
|
120 |
+
public function set_return_path( $email );
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Get the email body.
|
124 |
+
*
|
125 |
+
* @since 1.0.0
|
126 |
+
*
|
127 |
+
* @return string|array
|
128 |
+
*/
|
129 |
+
public function get_body();
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Get the email headers.
|
133 |
+
*
|
134 |
+
* @since 1.0.0
|
135 |
+
*
|
136 |
+
* @return array
|
137 |
+
*/
|
138 |
+
public function get_headers();
|
139 |
+
}
|
src/Providers/Mailgun/Mailer.php
CHANGED
@@ -1,299 +1,299 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Providers\Mailgun;
|
4 |
-
|
5 |
-
use WPMailSMTP\Providers\MailerAbstract;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Class Mailer.
|
9 |
-
*
|
10 |
-
* @since 1.0.0
|
11 |
-
*/
|
12 |
-
class Mailer extends MailerAbstract {
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Which response code from HTTP provider is considered to be successful?
|
16 |
-
*
|
17 |
-
* @var int
|
18 |
-
*/
|
19 |
-
protected $email_sent_code = 200;
|
20 |
-
|
21 |
-
/**
|
22 |
-
* URL to make an API request to.
|
23 |
-
*
|
24 |
-
* @var string
|
25 |
-
*/
|
26 |
-
protected $url = 'https://api.mailgun.net/v3/';
|
27 |
-
|
28 |
-
/**
|
29 |
-
* @inheritdoc
|
30 |
-
*/
|
31 |
-
public function __construct( $phpmailer ) {
|
32 |
-
|
33 |
-
// We want to prefill everything from \PHPMailer class.
|
34 |
-
parent::__construct( $phpmailer );
|
35 |
-
|
36 |
-
/*
|
37 |
-
* Append the url with a domain,
|
38 |
-
* to avoid passing the domain name as a query parameter with all requests.
|
39 |
-
*/
|
40 |
-
$this->url .= sanitize_text_field( $this->options->get( $this->mailer, 'domain' ) . '/messages' );
|
41 |
-
|
42 |
-
$this->set_header( 'Authorization', 'Basic ' . base64_encode( 'api:' . $this->options->get( $this->mailer, 'api_key' ) ) );
|
43 |
-
}
|
44 |
-
|
45 |
-
/**
|
46 |
-
* @inheritdoc
|
47 |
-
*/
|
48 |
-
public function set_from( $email, $name = '' ) {
|
49 |
-
|
50 |
-
if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
|
51 |
-
return;
|
52 |
-
}
|
53 |
-
|
54 |
-
if ( ! empty( $name ) ) {
|
55 |
-
$this->set_body_param(
|
56 |
-
array(
|
57 |
-
'from' => $name . ' <' . $email . '>',
|
58 |
-
)
|
59 |
-
);
|
60 |
-
} else {
|
61 |
-
$this->set_body_param(
|
62 |
-
array(
|
63 |
-
'from' => $email,
|
64 |
-
)
|
65 |
-
);
|
66 |
-
}
|
67 |
-
}
|
68 |
-
|
69 |
-
/**
|
70 |
-
* @inheritdoc
|
71 |
-
*/
|
72 |
-
public function set_recipients( $recipients ) {
|
73 |
-
|
74 |
-
if ( empty( $recipients ) ) {
|
75 |
-
return;
|
76 |
-
}
|
77 |
-
|
78 |
-
$default = array( 'to', 'cc', 'bcc' );
|
79 |
-
|
80 |
-
foreach ( $recipients as $kind => $emails ) {
|
81 |
-
if (
|
82 |
-
! in_array( $kind, $default, true ) ||
|
83 |
-
empty( $emails ) ||
|
84 |
-
! is_array( $emails )
|
85 |
-
) {
|
86 |
-
continue;
|
87 |
-
}
|
88 |
-
|
89 |
-
$data = array();
|
90 |
-
|
91 |
-
foreach ( $emails as $email ) {
|
92 |
-
$addr = isset( $email[0] ) ? $email[0] : false;
|
93 |
-
$name = isset( $email[1] ) ? $email[1] : false;
|
94 |
-
|
95 |
-
if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
|
96 |
-
continue;
|
97 |
-
}
|
98 |
-
|
99 |
-
if ( ! empty( $name ) ) {
|
100 |
-
$data[] = $name . ' <' . $addr . '>';
|
101 |
-
} else {
|
102 |
-
$data[] = $addr;
|
103 |
-
}
|
104 |
-
}
|
105 |
-
|
106 |
-
if ( ! empty( $data ) ) {
|
107 |
-
$this->set_body_param(
|
108 |
-
array(
|
109 |
-
$kind => implode( ', ', $data ),
|
110 |
-
)
|
111 |
-
);
|
112 |
-
}
|
113 |
-
}
|
114 |
-
}
|
115 |
-
|
116 |
-
/**
|
117 |
-
* @inheritdoc
|
118 |
-
*/
|
119 |
-
public function set_content( $content ) {
|
120 |
-
|
121 |
-
if ( is_array( $content ) ) {
|
122 |
-
|
123 |
-
$default = array( 'text', 'html' );
|
124 |
-
|
125 |
-
foreach ( $content as $type => $mail ) {
|
126 |
-
if (
|
127 |
-
! in_array( $type, $default, true ) ||
|
128 |
-
empty( $mail )
|
129 |
-
) {
|
130 |
-
continue;
|
131 |
-
}
|
132 |
-
|
133 |
-
$this->set_body_param(
|
134 |
-
array(
|
135 |
-
$type => $mail,
|
136 |
-
)
|
137 |
-
);
|
138 |
-
}
|
139 |
-
} else {
|
140 |
-
$type = 'text';
|
141 |
-
|
142 |
-
if ( $this->phpmailer->ContentType === 'text/html' ) {
|
143 |
-
$type = 'html';
|
144 |
-
}
|
145 |
-
|
146 |
-
if ( ! empty( $content ) ) {
|
147 |
-
$this->set_body_param(
|
148 |
-
array(
|
149 |
-
$type => $content,
|
150 |
-
)
|
151 |
-
);
|
152 |
-
}
|
153 |
-
}
|
154 |
-
}
|
155 |
-
|
156 |
-
/**
|
157 |
-
* It's the last one, so we can modify the whole body.
|
158 |
-
*
|
159 |
-
* @since 1.0.0
|
160 |
-
*
|
161 |
-
* @param array $attachments
|
162 |
-
*/
|
163 |
-
public function set_attachments( $attachments ) {
|
164 |
-
|
165 |
-
if ( empty( $attachments ) ) {
|
166 |
-
return;
|
167 |
-
}
|
168 |
-
|
169 |
-
$payload = '';
|
170 |
-
$data = array();
|
171 |
-
|
172 |
-
foreach ( $attachments as $attachment ) {
|
173 |
-
$file = false;
|
174 |
-
|
175 |
-
/*
|
176 |
-
* We are not using WP_Filesystem API as we can't reliably work with it.
|
177 |
-
* It is not always available, same as credentials for FTP.
|
178 |
-
*/
|
179 |
-
try {
|
180 |
-
if ( is_file( $attachment[0] ) && is_readable( $attachment[0] ) ) {
|
181 |
-
$file = file_get_contents( $attachment[0] );
|
182 |
-
}
|
183 |
-
} catch ( \Exception $e ) {
|
184 |
-
$file = false;
|
185 |
-
}
|
186 |
-
|
187 |
-
if ( $file === false ) {
|
188 |
-
continue;
|
189 |
-
}
|
190 |
-
|
191 |
-
$data[] = array(
|
192 |
-
'content' => $file,
|
193 |
-
'name' => $attachment[1],
|
194 |
-
);
|
195 |
-
}
|
196 |
-
|
197 |
-
if ( ! empty( $data ) ) {
|
198 |
-
|
199 |
-
// First, generate a boundary for the multipart message.
|
200 |
-
$boundary = base_convert( uniqid( 'boundary', true ), 10, 36 );
|
201 |
-
|
202 |
-
// Iterate through pre-built params and build a payload.
|
203 |
-
foreach ( $this->body as $key => $value ) {
|
204 |
-
if ( is_array( $value ) ) {
|
205 |
-
foreach ( $value as $child_key => $child_value ) {
|
206 |
-
$payload .= '--' . $boundary;
|
207 |
-
$payload .= "\r\n";
|
208 |
-
$payload .= 'Content-Disposition: form-data; name="' . $key . "\"\r\n\r\n";
|
209 |
-
$payload .= $child_value;
|
210 |
-
$payload .= "\r\n";
|
211 |
-
}
|
212 |
-
} else {
|
213 |
-
$payload .= '--' . $boundary;
|
214 |
-
$payload .= "\r\n";
|
215 |
-
$payload .= 'Content-Disposition: form-data; name="' . $key . '"' . "\r\n\r\n";
|
216 |
-
$payload .= $value;
|
217 |
-
$payload .= "\r\n";
|
218 |
-
}
|
219 |
-
}
|
220 |
-
|
221 |
-
// Now iterate through our attachments, and add them too.
|
222 |
-
foreach ( $data as $key => $attachment ) {
|
223 |
-
$payload .= '--' . $boundary;
|
224 |
-
$payload .= "\r\n";
|
225 |
-
$payload .= 'Content-Disposition: form-data; name="attachment[' . $key . ']"; filename="' . $attachment['name'] . '"' . "\r\n\r\n";
|
226 |
-
$payload .= $attachment['content'];
|
227 |
-
$payload .= "\r\n";
|
228 |
-
}
|
229 |
-
|
230 |
-
$payload .= '--' . $boundary . '--';
|
231 |
-
|
232 |
-
// Redefine the body the "dirty way".
|
233 |
-
$this->body = $payload;
|
234 |
-
|
235 |
-
$this->set_header( 'Content-Type', 'multipart/form-data; boundary=' . $boundary );
|
236 |
-
}
|
237 |
-
}
|
238 |
-
|
239 |
-
/**
|
240 |
-
* @inheritdoc
|
241 |
-
*/
|
242 |
-
public function set_reply_to( $reply_to ) {
|
243 |
-
|
244 |
-
if ( empty( $reply_to ) ) {
|
245 |
-
return;
|
246 |
-
}
|
247 |
-
|
248 |
-
$data = array();
|
249 |
-
|
250 |
-
foreach ( $reply_to as $key => $emails ) {
|
251 |
-
if (
|
252 |
-
empty( $emails ) ||
|
253 |
-
! is_array( $emails )
|
254 |
-
) {
|
255 |
-
continue;
|
256 |
-
}
|
257 |
-
|
258 |
-
$addr = isset( $emails[0] ) ? $emails[0] : false;
|
259 |
-
$name = isset( $emails[1] ) ? $emails[1] : false;
|
260 |
-
|
261 |
-
if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
|
262 |
-
continue;
|
263 |
-
}
|
264 |
-
|
265 |
-
if ( ! empty( $name ) ) {
|
266 |
-
$data[] = $name . ' <' . $addr . '>';
|
267 |
-
} else {
|
268 |
-
$data[] = $addr;
|
269 |
-
}
|
270 |
-
}
|
271 |
-
|
272 |
-
if ( ! empty( $data ) ) {
|
273 |
-
$this->set_body_param(
|
274 |
-
array(
|
275 |
-
'h:Reply-To' => implode( ',', $data ),
|
276 |
-
)
|
277 |
-
);
|
278 |
-
}
|
279 |
-
}
|
280 |
-
|
281 |
-
/**
|
282 |
-
* @inheritdoc
|
283 |
-
*/
|
284 |
-
public function set_return_path( $email ) {
|
285 |
-
|
286 |
-
if (
|
287 |
-
$this->options->get( 'mail', 'return_path' ) !== true ||
|
288 |
-
! filter_var( $email, FILTER_VALIDATE_EMAIL )
|
289 |
-
) {
|
290 |
-
return;
|
291 |
-
}
|
292 |
-
|
293 |
-
$this->set_body_param(
|
294 |
-
array(
|
295 |
-
'sender' => $email,
|
296 |
-
)
|
297 |
-
);
|
298 |
-
}
|
299 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Providers\Mailgun;
|
4 |
+
|
5 |
+
use WPMailSMTP\Providers\MailerAbstract;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class Mailer.
|
9 |
+
*
|
10 |
+
* @since 1.0.0
|
11 |
+
*/
|
12 |
+
class Mailer extends MailerAbstract {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Which response code from HTTP provider is considered to be successful?
|
16 |
+
*
|
17 |
+
* @var int
|
18 |
+
*/
|
19 |
+
protected $email_sent_code = 200;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* URL to make an API request to.
|
23 |
+
*
|
24 |
+
* @var string
|
25 |
+
*/
|
26 |
+
protected $url = 'https://api.mailgun.net/v3/';
|
27 |
+
|
28 |
+
/**
|
29 |
+
* @inheritdoc
|
30 |
+
*/
|
31 |
+
public function __construct( $phpmailer ) {
|
32 |
+
|
33 |
+
// We want to prefill everything from \PHPMailer class.
|
34 |
+
parent::__construct( $phpmailer );
|
35 |
+
|
36 |
+
/*
|
37 |
+
* Append the url with a domain,
|
38 |
+
* to avoid passing the domain name as a query parameter with all requests.
|
39 |
+
*/
|
40 |
+
$this->url .= sanitize_text_field( $this->options->get( $this->mailer, 'domain' ) . '/messages' );
|
41 |
+
|
42 |
+
$this->set_header( 'Authorization', 'Basic ' . base64_encode( 'api:' . $this->options->get( $this->mailer, 'api_key' ) ) );
|
43 |
+
}
|
44 |
+
|
45 |
+
/**
|
46 |
+
* @inheritdoc
|
47 |
+
*/
|
48 |
+
public function set_from( $email, $name = '' ) {
|
49 |
+
|
50 |
+
if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
|
51 |
+
return;
|
52 |
+
}
|
53 |
+
|
54 |
+
if ( ! empty( $name ) ) {
|
55 |
+
$this->set_body_param(
|
56 |
+
array(
|
57 |
+
'from' => $name . ' <' . $email . '>',
|
58 |
+
)
|
59 |
+
);
|
60 |
+
} else {
|
61 |
+
$this->set_body_param(
|
62 |
+
array(
|
63 |
+
'from' => $email,
|
64 |
+
)
|
65 |
+
);
|
66 |
+
}
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* @inheritdoc
|
71 |
+
*/
|
72 |
+
public function set_recipients( $recipients ) {
|
73 |
+
|
74 |
+
if ( empty( $recipients ) ) {
|
75 |
+
return;
|
76 |
+
}
|
77 |
+
|
78 |
+
$default = array( 'to', 'cc', 'bcc' );
|
79 |
+
|
80 |
+
foreach ( $recipients as $kind => $emails ) {
|
81 |
+
if (
|
82 |
+
! in_array( $kind, $default, true ) ||
|
83 |
+
empty( $emails ) ||
|
84 |
+
! is_array( $emails )
|
85 |
+
) {
|
86 |
+
continue;
|
87 |
+
}
|
88 |
+
|
89 |
+
$data = array();
|
90 |
+
|
91 |
+
foreach ( $emails as $email ) {
|
92 |
+
$addr = isset( $email[0] ) ? $email[0] : false;
|
93 |
+
$name = isset( $email[1] ) ? $email[1] : false;
|
94 |
+
|
95 |
+
if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
|
96 |
+
continue;
|
97 |
+
}
|
98 |
+
|
99 |
+
if ( ! empty( $name ) ) {
|
100 |
+
$data[] = $name . ' <' . $addr . '>';
|
101 |
+
} else {
|
102 |
+
$data[] = $addr;
|
103 |
+
}
|
104 |
+
}
|
105 |
+
|
106 |
+
if ( ! empty( $data ) ) {
|
107 |
+
$this->set_body_param(
|
108 |
+
array(
|
109 |
+
$kind => implode( ', ', $data ),
|
110 |
+
)
|
111 |
+
);
|
112 |
+
}
|
113 |
+
}
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* @inheritdoc
|
118 |
+
*/
|
119 |
+
public function set_content( $content ) {
|
120 |
+
|
121 |
+
if ( is_array( $content ) ) {
|
122 |
+
|
123 |
+
$default = array( 'text', 'html' );
|
124 |
+
|
125 |
+
foreach ( $content as $type => $mail ) {
|
126 |
+
if (
|
127 |
+
! in_array( $type, $default, true ) ||
|
128 |
+
empty( $mail )
|
129 |
+
) {
|
130 |
+
continue;
|
131 |
+
}
|
132 |
+
|
133 |
+
$this->set_body_param(
|
134 |
+
array(
|
135 |
+
$type => $mail,
|
136 |
+
)
|
137 |
+
);
|
138 |
+
}
|
139 |
+
} else {
|
140 |
+
$type = 'text';
|
141 |
+
|
142 |
+
if ( $this->phpmailer->ContentType === 'text/html' ) {
|
143 |
+
$type = 'html';
|
144 |
+
}
|
145 |
+
|
146 |
+
if ( ! empty( $content ) ) {
|
147 |
+
$this->set_body_param(
|
148 |
+
array(
|
149 |
+
$type => $content,
|
150 |
+
)
|
151 |
+
);
|
152 |
+
}
|
153 |
+
}
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* It's the last one, so we can modify the whole body.
|
158 |
+
*
|
159 |
+
* @since 1.0.0
|
160 |
+
*
|
161 |
+
* @param array $attachments
|
162 |
+
*/
|
163 |
+
public function set_attachments( $attachments ) {
|
164 |
+
|
165 |
+
if ( empty( $attachments ) ) {
|
166 |
+
return;
|
167 |
+
}
|
168 |
+
|
169 |
+
$payload = '';
|
170 |
+
$data = array();
|
171 |
+
|
172 |
+
foreach ( $attachments as $attachment ) {
|
173 |
+
$file = false;
|
174 |
+
|
175 |
+
/*
|
176 |
+
* We are not using WP_Filesystem API as we can't reliably work with it.
|
177 |
+
* It is not always available, same as credentials for FTP.
|
178 |
+
*/
|
179 |
+
try {
|
180 |
+
if ( is_file( $attachment[0] ) && is_readable( $attachment[0] ) ) {
|
181 |
+
$file = file_get_contents( $attachment[0] );
|
182 |
+
}
|
183 |
+
} catch ( \Exception $e ) {
|
184 |
+
$file = false;
|
185 |
+
}
|
186 |
+
|
187 |
+
if ( $file === false ) {
|
188 |
+
continue;
|
189 |
+
}
|
190 |
+
|
191 |
+
$data[] = array(
|
192 |
+
'content' => $file,
|
193 |
+
'name' => $attachment[1],
|
194 |
+
);
|
195 |
+
}
|
196 |
+
|
197 |
+
if ( ! empty( $data ) ) {
|
198 |
+
|
199 |
+
// First, generate a boundary for the multipart message.
|
200 |
+
$boundary = base_convert( uniqid( 'boundary', true ), 10, 36 );
|
201 |
+
|
202 |
+
// Iterate through pre-built params and build a payload.
|
203 |
+
foreach ( $this->body as $key => $value ) {
|
204 |
+
if ( is_array( $value ) ) {
|
205 |
+
foreach ( $value as $child_key => $child_value ) {
|
206 |
+
$payload .= '--' . $boundary;
|
207 |
+
$payload .= "\r\n";
|
208 |
+
$payload .= 'Content-Disposition: form-data; name="' . $key . "\"\r\n\r\n";
|
209 |
+
$payload .= $child_value;
|
210 |
+
$payload .= "\r\n";
|
211 |
+
}
|
212 |
+
} else {
|
213 |
+
$payload .= '--' . $boundary;
|
214 |
+
$payload .= "\r\n";
|
215 |
+
$payload .= 'Content-Disposition: form-data; name="' . $key . '"' . "\r\n\r\n";
|
216 |
+
$payload .= $value;
|
217 |
+
$payload .= "\r\n";
|
218 |
+
}
|
219 |
+
}
|
220 |
+
|
221 |
+
// Now iterate through our attachments, and add them too.
|
222 |
+
foreach ( $data as $key => $attachment ) {
|
223 |
+
$payload .= '--' . $boundary;
|
224 |
+
$payload .= "\r\n";
|
225 |
+
$payload .= 'Content-Disposition: form-data; name="attachment[' . $key . ']"; filename="' . $attachment['name'] . '"' . "\r\n\r\n";
|
226 |
+
$payload .= $attachment['content'];
|
227 |
+
$payload .= "\r\n";
|
228 |
+
}
|
229 |
+
|
230 |
+
$payload .= '--' . $boundary . '--';
|
231 |
+
|
232 |
+
// Redefine the body the "dirty way".
|
233 |
+
$this->body = $payload;
|
234 |
+
|
235 |
+
$this->set_header( 'Content-Type', 'multipart/form-data; boundary=' . $boundary );
|
236 |
+
}
|
237 |
+
}
|
238 |
+
|
239 |
+
/**
|
240 |
+
* @inheritdoc
|
241 |
+
*/
|
242 |
+
public function set_reply_to( $reply_to ) {
|
243 |
+
|
244 |
+
if ( empty( $reply_to ) ) {
|
245 |
+
return;
|
246 |
+
}
|
247 |
+
|
248 |
+
$data = array();
|
249 |
+
|
250 |
+
foreach ( $reply_to as $key => $emails ) {
|
251 |
+
if (
|
252 |
+
empty( $emails ) ||
|
253 |
+
! is_array( $emails )
|
254 |
+
) {
|
255 |
+
continue;
|
256 |
+
}
|
257 |
+
|
258 |
+
$addr = isset( $emails[0] ) ? $emails[0] : false;
|
259 |
+
$name = isset( $emails[1] ) ? $emails[1] : false;
|
260 |
+
|
261 |
+
if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
|
262 |
+
continue;
|
263 |
+
}
|
264 |
+
|
265 |
+
if ( ! empty( $name ) ) {
|
266 |
+
$data[] = $name . ' <' . $addr . '>';
|
267 |
+
} else {
|
268 |
+
$data[] = $addr;
|
269 |
+
}
|
270 |
+
}
|
271 |
+
|
272 |
+
if ( ! empty( $data ) ) {
|
273 |
+
$this->set_body_param(
|
274 |
+
array(
|
275 |
+
'h:Reply-To' => implode( ',', $data ),
|
276 |
+
)
|
277 |
+
);
|
278 |
+
}
|
279 |
+
}
|
280 |
+
|
281 |
+
/**
|
282 |
+
* @inheritdoc
|
283 |
+
*/
|
284 |
+
public function set_return_path( $email ) {
|
285 |
+
|
286 |
+
if (
|
287 |
+
$this->options->get( 'mail', 'return_path' ) !== true ||
|
288 |
+
! filter_var( $email, FILTER_VALIDATE_EMAIL )
|
289 |
+
) {
|
290 |
+
return;
|
291 |
+
}
|
292 |
+
|
293 |
+
$this->set_body_param(
|
294 |
+
array(
|
295 |
+
'sender' => $email,
|
296 |
+
)
|
297 |
+
);
|
298 |
+
}
|
299 |
+
}
|
src/Providers/Mailgun/Options.php
CHANGED
@@ -1,106 +1,106 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Providers\Mailgun;
|
4 |
-
|
5 |
-
use WPMailSMTP\Providers\OptionAbstract;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Class Option.
|
9 |
-
*
|
10 |
-
* @since 1.0.0
|
11 |
-
*/
|
12 |
-
class Options extends OptionAbstract {
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Mailgun constructor.
|
16 |
-
*
|
17 |
-
* @since 1.0.0
|
18 |
-
*/
|
19 |
-
public function __construct() {
|
20 |
-
|
21 |
-
parent::__construct(
|
22 |
-
array(
|
23 |
-
'logo_url' => wp_mail_smtp()->plugin_url . '/assets/images/mailgun.png',
|
24 |
-
'slug' => 'mailgun',
|
25 |
-
'title' => esc_html__( 'Mailgun', 'wp-mail-smtp' ),
|
26 |
-
'description' => sprintf(
|
27 |
-
wp_kses(
|
28 |
-
/* translators: %1$s - opening link tag; %2$s - closing link tag; %3$s - opening link tag; %4$s - closing link tag. */
|
29 |
-
__( '%1$sMailgun%2$s is one of the leading transactional email services trusted by over 10,000 website and application developers. They provide users 10,000 free emails per month.<br><br>Read our %3$sMailgun documentation%4$s to learn how to configure Mailgun and improve your email deliverability.', 'wp-mail-smtp' ),
|
30 |
-
array(
|
31 |
-
'br' => array(),
|
32 |
-
'a' => array(
|
33 |
-
'href' => array(),
|
34 |
-
'rel' => array(),
|
35 |
-
'target' => array(),
|
36 |
-
),
|
37 |
-
)
|
38 |
-
),
|
39 |
-
'<a href="https://www.mailgun.com" target="_blank" rel="noopener noreferrer">',
|
40 |
-
'</a>',
|
41 |
-
'<a href="https://wpforms.com/how-to-send-wordpress-emails-with-mailgun/" target="_blank" rel="noopener noreferrer">',
|
42 |
-
'</a>'
|
43 |
-
),
|
44 |
-
)
|
45 |
-
);
|
46 |
-
}
|
47 |
-
|
48 |
-
/**
|
49 |
-
* @inheritdoc
|
50 |
-
*/
|
51 |
-
public function display_options() {
|
52 |
-
?>
|
53 |
-
|
54 |
-
<!-- API Key -->
|
55 |
-
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-api_key" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
56 |
-
<div class="wp-mail-smtp-setting-label">
|
57 |
-
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"><?php esc_html_e( 'Private API Key', 'wp-mail-smtp' ); ?></label>
|
58 |
-
</div>
|
59 |
-
<div class="wp-mail-smtp-setting-field">
|
60 |
-
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][api_key]" type="text"
|
61 |
-
value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'api_key' ) ); ?>"
|
62 |
-
<?php echo $this->options->is_const_defined( $this->get_slug(), 'api_key' ) ? 'disabled' : ''; ?>
|
63 |
-
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key" spellcheck="false"
|
64 |
-
/>
|
65 |
-
<p class="desc">
|
66 |
-
<?php
|
67 |
-
printf(
|
68 |
-
/* translators: %s - API key link. */
|
69 |
-
esc_html__( 'Follow this link to get an API Key from Mailgun: %s.', 'wp-mail-smtp' ),
|
70 |
-
'<a href="https://app.mailgun.com/app/account/security" target="_blank" rel="noopener noreferrer">' .
|
71 |
-
esc_html__( 'Get a Private API Key', 'wp-mail-smtp' ) .
|
72 |
-
'</a>'
|
73 |
-
);
|
74 |
-
?>
|
75 |
-
</p>
|
76 |
-
</div>
|
77 |
-
</div>
|
78 |
-
|
79 |
-
<!-- Domain -->
|
80 |
-
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-domain" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
81 |
-
<div class="wp-mail-smtp-setting-label">
|
82 |
-
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-domain"><?php esc_html_e( 'Domain Name', 'wp-mail-smtp' ); ?></label>
|
83 |
-
</div>
|
84 |
-
<div class="wp-mail-smtp-setting-field">
|
85 |
-
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][domain]" type="text"
|
86 |
-
value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'domain' ) ); ?>"
|
87 |
-
<?php echo $this->options->is_const_defined( $this->get_slug(), 'domain' ) ? 'disabled' : ''; ?>
|
88 |
-
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-domain" spellcheck="false"
|
89 |
-
/>
|
90 |
-
<p class="desc">
|
91 |
-
<?php
|
92 |
-
printf(
|
93 |
-
/* translators: %s - Domain Name link. */
|
94 |
-
esc_html__( 'Follow this link to get a Domain Name from Mailgun: %s.', 'wp-mail-smtp' ),
|
95 |
-
'<a href="https://app.mailgun.com/app/domains" target="_blank" rel="noopener noreferrer">' .
|
96 |
-
esc_html__( 'Get a Domain Name', 'wp-mail-smtp' ) .
|
97 |
-
'</a>'
|
98 |
-
);
|
99 |
-
?>
|
100 |
-
</p>
|
101 |
-
</div>
|
102 |
-
</div>
|
103 |
-
|
104 |
-
<?php
|
105 |
-
}
|
106 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Providers\Mailgun;
|
4 |
+
|
5 |
+
use WPMailSMTP\Providers\OptionAbstract;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class Option.
|
9 |
+
*
|
10 |
+
* @since 1.0.0
|
11 |
+
*/
|
12 |
+
class Options extends OptionAbstract {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Mailgun constructor.
|
16 |
+
*
|
17 |
+
* @since 1.0.0
|
18 |
+
*/
|
19 |
+
public function __construct() {
|
20 |
+
|
21 |
+
parent::__construct(
|
22 |
+
array(
|
23 |
+
'logo_url' => wp_mail_smtp()->plugin_url . '/assets/images/mailgun.png',
|
24 |
+
'slug' => 'mailgun',
|
25 |
+
'title' => esc_html__( 'Mailgun', 'wp-mail-smtp' ),
|
26 |
+
'description' => sprintf(
|
27 |
+
wp_kses(
|
28 |
+
/* translators: %1$s - opening link tag; %2$s - closing link tag; %3$s - opening link tag; %4$s - closing link tag. */
|
29 |
+
__( '%1$sMailgun%2$s is one of the leading transactional email services trusted by over 10,000 website and application developers. They provide users 10,000 free emails per month.<br><br>Read our %3$sMailgun documentation%4$s to learn how to configure Mailgun and improve your email deliverability.', 'wp-mail-smtp' ),
|
30 |
+
array(
|
31 |
+
'br' => array(),
|
32 |
+
'a' => array(
|
33 |
+
'href' => array(),
|
34 |
+
'rel' => array(),
|
35 |
+
'target' => array(),
|
36 |
+
),
|
37 |
+
)
|
38 |
+
),
|
39 |
+
'<a href="https://www.mailgun.com" target="_blank" rel="noopener noreferrer">',
|
40 |
+
'</a>',
|
41 |
+
'<a href="https://wpforms.com/how-to-send-wordpress-emails-with-mailgun/" target="_blank" rel="noopener noreferrer">',
|
42 |
+
'</a>'
|
43 |
+
),
|
44 |
+
)
|
45 |
+
);
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* @inheritdoc
|
50 |
+
*/
|
51 |
+
public function display_options() {
|
52 |
+
?>
|
53 |
+
|
54 |
+
<!-- API Key -->
|
55 |
+
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-api_key" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
56 |
+
<div class="wp-mail-smtp-setting-label">
|
57 |
+
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"><?php esc_html_e( 'Private API Key', 'wp-mail-smtp' ); ?></label>
|
58 |
+
</div>
|
59 |
+
<div class="wp-mail-smtp-setting-field">
|
60 |
+
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][api_key]" type="text"
|
61 |
+
value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'api_key' ) ); ?>"
|
62 |
+
<?php echo $this->options->is_const_defined( $this->get_slug(), 'api_key' ) ? 'disabled' : ''; ?>
|
63 |
+
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key" spellcheck="false"
|
64 |
+
/>
|
65 |
+
<p class="desc">
|
66 |
+
<?php
|
67 |
+
printf(
|
68 |
+
/* translators: %s - API key link. */
|
69 |
+
esc_html__( 'Follow this link to get an API Key from Mailgun: %s.', 'wp-mail-smtp' ),
|
70 |
+
'<a href="https://app.mailgun.com/app/account/security" target="_blank" rel="noopener noreferrer">' .
|
71 |
+
esc_html__( 'Get a Private API Key', 'wp-mail-smtp' ) .
|
72 |
+
'</a>'
|
73 |
+
);
|
74 |
+
?>
|
75 |
+
</p>
|
76 |
+
</div>
|
77 |
+
</div>
|
78 |
+
|
79 |
+
<!-- Domain -->
|
80 |
+
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-domain" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
81 |
+
<div class="wp-mail-smtp-setting-label">
|
82 |
+
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-domain"><?php esc_html_e( 'Domain Name', 'wp-mail-smtp' ); ?></label>
|
83 |
+
</div>
|
84 |
+
<div class="wp-mail-smtp-setting-field">
|
85 |
+
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][domain]" type="text"
|
86 |
+
value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'domain' ) ); ?>"
|
87 |
+
<?php echo $this->options->is_const_defined( $this->get_slug(), 'domain' ) ? 'disabled' : ''; ?>
|
88 |
+
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-domain" spellcheck="false"
|
89 |
+
/>
|
90 |
+
<p class="desc">
|
91 |
+
<?php
|
92 |
+
printf(
|
93 |
+
/* translators: %s - Domain Name link. */
|
94 |
+
esc_html__( 'Follow this link to get a Domain Name from Mailgun: %s.', 'wp-mail-smtp' ),
|
95 |
+
'<a href="https://app.mailgun.com/app/domains" target="_blank" rel="noopener noreferrer">' .
|
96 |
+
esc_html__( 'Get a Domain Name', 'wp-mail-smtp' ) .
|
97 |
+
'</a>'
|
98 |
+
);
|
99 |
+
?>
|
100 |
+
</p>
|
101 |
+
</div>
|
102 |
+
</div>
|
103 |
+
|
104 |
+
<?php
|
105 |
+
}
|
106 |
+
}
|
src/Providers/OptionAbstract.php
CHANGED
@@ -1,291 +1,312 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Providers;
|
4 |
-
|
5 |
-
use WPMailSMTP\Options;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Abstract Class ProviderAbstract to contain common providers functionality.
|
9 |
-
*
|
10 |
-
* @since 1.0.0
|
11 |
-
*/
|
12 |
-
abstract class OptionAbstract implements OptionInterface {
|
13 |
-
|
14 |
-
/**
|
15 |
-
* @var string
|
16 |
-
*/
|
17 |
-
private $logo_url = '';
|
18 |
-
/**
|
19 |
-
* @var string
|
20 |
-
*/
|
21 |
-
private $slug = '';
|
22 |
-
/**
|
23 |
-
* @var string
|
24 |
-
*/
|
25 |
-
private $title = '';
|
26 |
-
/**
|
27 |
-
* @var string
|
28 |
-
*/
|
29 |
-
private $description = '';
|
30 |
-
/**
|
31 |
-
* @var string
|
32 |
-
*/
|
33 |
-
private $php = WPMS_PHP_VER;
|
34 |
-
/**
|
35 |
-
* @var Options
|
36 |
-
*/
|
37 |
-
protected $options;
|
38 |
-
|
39 |
-
/**
|
40 |
-
* ProviderAbstract constructor.
|
41 |
-
*
|
42 |
-
* @since 1.0.0
|
43 |
-
*
|
44 |
-
* @param array $params
|
45 |
-
*/
|
46 |
-
public function __construct( $params ) {
|
47 |
-
|
48 |
-
if (
|
49 |
-
empty( $params['slug'] ) ||
|
50 |
-
empty( $params['title'] )
|
51 |
-
) {
|
52 |
-
return;
|
53 |
-
}
|
54 |
-
|
55 |
-
$this->slug = sanitize_key( $params['slug'] );
|
56 |
-
$this->title = sanitize_text_field( $params['title'] );
|
57 |
-
|
58 |
-
if ( ! empty( $params['description'] ) ) {
|
59 |
-
$this->description = wp_kses( $params['description'],
|
60 |
-
array(
|
61 |
-
'br' => array(),
|
62 |
-
'a' => array(
|
63 |
-
'href' => array(),
|
64 |
-
'rel' => array(),
|
65 |
-
'target' => array(),
|
66 |
-
),
|
67 |
-
)
|
68 |
-
);
|
69 |
-
}
|
70 |
-
|
71 |
-
if ( ! empty( $params['php'] ) ) {
|
72 |
-
$this->php = sanitize_text_field( $params['php'] );
|
73 |
-
}
|
74 |
-
|
75 |
-
if ( ! empty( $params['logo_url'] ) ) {
|
76 |
-
$this->logo_url = esc_url_raw( $params['logo_url'] );
|
77 |
-
}
|
78 |
-
|
79 |
-
$this->options = new Options();
|
80 |
-
}
|
81 |
-
|
82 |
-
/**
|
83 |
-
* @inheritdoc
|
84 |
-
*/
|
85 |
-
public function get_logo_url() {
|
86 |
-
return apply_filters( 'wp_mail_smtp_providers_provider_get_logo_url', $this->logo_url, $this );
|
87 |
-
}
|
88 |
-
|
89 |
-
/**
|
90 |
-
* @inheritdoc
|
91 |
-
*/
|
92 |
-
public function get_slug() {
|
93 |
-
return apply_filters( 'wp_mail_smtp_providers_provider_get_slug', $this->slug, $this );
|
94 |
-
}
|
95 |
-
|
96 |
-
/**
|
97 |
-
* @inheritdoc
|
98 |
-
*/
|
99 |
-
public function get_title() {
|
100 |
-
return apply_filters( 'wp_mail_smtp_providers_provider_get_title', $this->title, $this );
|
101 |
-
}
|
102 |
-
|
103 |
-
/**
|
104 |
-
* @inheritdoc
|
105 |
-
*/
|
106 |
-
public function get_description() {
|
107 |
-
return apply_filters( 'wp_mail_smtp_providers_provider_get_description', $this->description, $this );
|
108 |
-
}
|
109 |
-
|
110 |
-
/**
|
111 |
-
* @inheritdoc
|
112 |
-
*/
|
113 |
-
public function get_php_version() {
|
114 |
-
return apply_filters( 'wp_mail_smtp_providers_provider_get_php_version', $this->php, $this );
|
115 |
-
}
|
116 |
-
|
117 |
-
/**
|
118 |
-
* @inheritdoc
|
119 |
-
*/
|
120 |
-
public function display_options() {
|
121 |
-
?>
|
122 |
-
|
123 |
-
<!-- SMTP Host -->
|
124 |
-
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-host" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
125 |
-
<div class="wp-mail-smtp-setting-label">
|
126 |
-
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-host"><?php esc_html_e( 'SMTP Host', 'wp-mail-smtp' ); ?></label>
|
127 |
-
</div>
|
128 |
-
<div class="wp-mail-smtp-setting-field">
|
129 |
-
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][host]" type="text"
|
130 |
-
value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'host' ) ); ?>"
|
131 |
-
<?php echo $this->options->is_const_defined( $this->get_slug(), 'host' ) ? 'disabled' : ''; ?>
|
132 |
-
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-host" spellcheck="false"
|
133 |
-
/>
|
134 |
-
</div>
|
135 |
-
</div>
|
136 |
-
|
137 |
-
<!-- SMTP Port -->
|
138 |
-
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-port" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-number wp-mail-smtp-clear">
|
139 |
-
<div class="wp-mail-smtp-setting-label">
|
140 |
-
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-port"><?php esc_html_e( 'SMTP Port', 'wp-mail-smtp' ); ?></label>
|
141 |
-
</div>
|
142 |
-
<div class="wp-mail-smtp-setting-field">
|
143 |
-
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][port]" type="number"
|
144 |
-
value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'port' ) ); ?>"
|
145 |
-
<?php echo $this->options->is_const_defined( $this->get_slug(), 'port' ) ? 'disabled' : ''; ?>
|
146 |
-
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-port" class="small-text" spellcheck="false"
|
147 |
-
/>
|
148 |
-
</div>
|
149 |
-
</div>
|
150 |
-
|
151 |
-
<!-- SMTP Encryption -->
|
152 |
-
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-encryption" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-radio wp-mail-smtp-clear">
|
153 |
-
<div class="wp-mail-smtp-setting-label">
|
154 |
-
<label><?php esc_html_e( 'Encryption', 'wp-mail-smtp' ); ?></label>
|
155 |
-
</div>
|
156 |
-
<div class="wp-mail-smtp-setting-field">
|
157 |
-
|
158 |
-
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-none">
|
159 |
-
<input type="radio" id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-none"
|
160 |
-
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][encryption]" value="none"
|
161 |
-
<?php echo $this->options->is_const_defined( $this->get_slug(), 'encryption' ) ? 'disabled' : ''; ?>
|
162 |
-
<?php checked( 'none', $this->options->get( $this->get_slug(), 'encryption' ) ); ?>
|
163 |
-
/>
|
164 |
-
<?php esc_html_e( 'None', 'wp-mail-smtp' ); ?>
|
165 |
-
</label>
|
166 |
-
|
167 |
-
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-ssl">
|
168 |
-
<input type="radio" id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-ssl"
|
169 |
-
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][encryption]" value="ssl"
|
170 |
-
<?php echo $this->options->is_const_defined( $this->get_slug(), 'encryption' ) ? 'disabled' : ''; ?>
|
171 |
-
<?php checked( 'ssl', $this->options->get( $this->get_slug(), 'encryption' ) ); ?>
|
172 |
-
/>
|
173 |
-
<?php esc_html_e( 'SSL', 'wp-mail-smtp' ); ?>
|
174 |
-
</label>
|
175 |
-
|
176 |
-
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-tls">
|
177 |
-
<input type="radio" id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-tls"
|
178 |
-
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][encryption]" value="tls"
|
179 |
-
<?php echo $this->options->is_const_defined( $this->get_slug(), 'encryption' ) ? 'disabled' : ''; ?>
|
180 |
-
<?php checked( 'tls', $this->options->get( $this->get_slug(), 'encryption' ) ); ?>
|
181 |
-
/>
|
182 |
-
<?php esc_html_e( 'TLS', 'wp-mail-smtp' ); ?>
|
183 |
-
</label>
|
184 |
-
|
185 |
-
<p class="desc">
|
186 |
-
<?php esc_html_e( 'TLS is
|
187 |
-
</p>
|
188 |
-
</div>
|
189 |
-
</div>
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
<?php
|
202 |
-
|
203 |
-
|
204 |
-
<span class="wp-mail-smtp-setting-toggle-
|
205 |
-
<span class="wp-mail-smtp-setting-toggle-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
</div>
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Providers;
|
4 |
+
|
5 |
+
use WPMailSMTP\Options;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Abstract Class ProviderAbstract to contain common providers functionality.
|
9 |
+
*
|
10 |
+
* @since 1.0.0
|
11 |
+
*/
|
12 |
+
abstract class OptionAbstract implements OptionInterface {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @var string
|
16 |
+
*/
|
17 |
+
private $logo_url = '';
|
18 |
+
/**
|
19 |
+
* @var string
|
20 |
+
*/
|
21 |
+
private $slug = '';
|
22 |
+
/**
|
23 |
+
* @var string
|
24 |
+
*/
|
25 |
+
private $title = '';
|
26 |
+
/**
|
27 |
+
* @var string
|
28 |
+
*/
|
29 |
+
private $description = '';
|
30 |
+
/**
|
31 |
+
* @var string
|
32 |
+
*/
|
33 |
+
private $php = WPMS_PHP_VER;
|
34 |
+
/**
|
35 |
+
* @var Options
|
36 |
+
*/
|
37 |
+
protected $options;
|
38 |
+
|
39 |
+
/**
|
40 |
+
* ProviderAbstract constructor.
|
41 |
+
*
|
42 |
+
* @since 1.0.0
|
43 |
+
*
|
44 |
+
* @param array $params
|
45 |
+
*/
|
46 |
+
public function __construct( $params ) {
|
47 |
+
|
48 |
+
if (
|
49 |
+
empty( $params['slug'] ) ||
|
50 |
+
empty( $params['title'] )
|
51 |
+
) {
|
52 |
+
return;
|
53 |
+
}
|
54 |
+
|
55 |
+
$this->slug = sanitize_key( $params['slug'] );
|
56 |
+
$this->title = sanitize_text_field( $params['title'] );
|
57 |
+
|
58 |
+
if ( ! empty( $params['description'] ) ) {
|
59 |
+
$this->description = wp_kses( $params['description'],
|
60 |
+
array(
|
61 |
+
'br' => array(),
|
62 |
+
'a' => array(
|
63 |
+
'href' => array(),
|
64 |
+
'rel' => array(),
|
65 |
+
'target' => array(),
|
66 |
+
),
|
67 |
+
)
|
68 |
+
);
|
69 |
+
}
|
70 |
+
|
71 |
+
if ( ! empty( $params['php'] ) ) {
|
72 |
+
$this->php = sanitize_text_field( $params['php'] );
|
73 |
+
}
|
74 |
+
|
75 |
+
if ( ! empty( $params['logo_url'] ) ) {
|
76 |
+
$this->logo_url = esc_url_raw( $params['logo_url'] );
|
77 |
+
}
|
78 |
+
|
79 |
+
$this->options = new Options();
|
80 |
+
}
|
81 |
+
|
82 |
+
/**
|
83 |
+
* @inheritdoc
|
84 |
+
*/
|
85 |
+
public function get_logo_url() {
|
86 |
+
return apply_filters( 'wp_mail_smtp_providers_provider_get_logo_url', $this->logo_url, $this );
|
87 |
+
}
|
88 |
+
|
89 |
+
/**
|
90 |
+
* @inheritdoc
|
91 |
+
*/
|
92 |
+
public function get_slug() {
|
93 |
+
return apply_filters( 'wp_mail_smtp_providers_provider_get_slug', $this->slug, $this );
|
94 |
+
}
|
95 |
+
|
96 |
+
/**
|
97 |
+
* @inheritdoc
|
98 |
+
*/
|
99 |
+
public function get_title() {
|
100 |
+
return apply_filters( 'wp_mail_smtp_providers_provider_get_title', $this->title, $this );
|
101 |
+
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* @inheritdoc
|
105 |
+
*/
|
106 |
+
public function get_description() {
|
107 |
+
return apply_filters( 'wp_mail_smtp_providers_provider_get_description', $this->description, $this );
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* @inheritdoc
|
112 |
+
*/
|
113 |
+
public function get_php_version() {
|
114 |
+
return apply_filters( 'wp_mail_smtp_providers_provider_get_php_version', $this->php, $this );
|
115 |
+
}
|
116 |
+
|
117 |
+
/**
|
118 |
+
* @inheritdoc
|
119 |
+
*/
|
120 |
+
public function display_options() {
|
121 |
+
?>
|
122 |
+
|
123 |
+
<!-- SMTP Host -->
|
124 |
+
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-host" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
125 |
+
<div class="wp-mail-smtp-setting-label">
|
126 |
+
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-host"><?php esc_html_e( 'SMTP Host', 'wp-mail-smtp' ); ?></label>
|
127 |
+
</div>
|
128 |
+
<div class="wp-mail-smtp-setting-field">
|
129 |
+
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][host]" type="text"
|
130 |
+
value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'host' ) ); ?>"
|
131 |
+
<?php echo $this->options->is_const_defined( $this->get_slug(), 'host' ) ? 'disabled' : ''; ?>
|
132 |
+
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-host" spellcheck="false"
|
133 |
+
/>
|
134 |
+
</div>
|
135 |
+
</div>
|
136 |
+
|
137 |
+
<!-- SMTP Port -->
|
138 |
+
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-port" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-number wp-mail-smtp-clear">
|
139 |
+
<div class="wp-mail-smtp-setting-label">
|
140 |
+
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-port"><?php esc_html_e( 'SMTP Port', 'wp-mail-smtp' ); ?></label>
|
141 |
+
</div>
|
142 |
+
<div class="wp-mail-smtp-setting-field">
|
143 |
+
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][port]" type="number"
|
144 |
+
value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'port' ) ); ?>"
|
145 |
+
<?php echo $this->options->is_const_defined( $this->get_slug(), 'port' ) ? 'disabled' : ''; ?>
|
146 |
+
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-port" class="small-text" spellcheck="false"
|
147 |
+
/>
|
148 |
+
</div>
|
149 |
+
</div>
|
150 |
+
|
151 |
+
<!-- SMTP Encryption -->
|
152 |
+
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-encryption" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-radio wp-mail-smtp-clear">
|
153 |
+
<div class="wp-mail-smtp-setting-label">
|
154 |
+
<label><?php esc_html_e( 'Encryption', 'wp-mail-smtp' ); ?></label>
|
155 |
+
</div>
|
156 |
+
<div class="wp-mail-smtp-setting-field">
|
157 |
+
|
158 |
+
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-none">
|
159 |
+
<input type="radio" id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-none"
|
160 |
+
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][encryption]" value="none"
|
161 |
+
<?php echo $this->options->is_const_defined( $this->get_slug(), 'encryption' ) ? 'disabled' : ''; ?>
|
162 |
+
<?php checked( 'none', $this->options->get( $this->get_slug(), 'encryption' ) ); ?>
|
163 |
+
/>
|
164 |
+
<?php esc_html_e( 'None', 'wp-mail-smtp' ); ?>
|
165 |
+
</label>
|
166 |
+
|
167 |
+
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-ssl">
|
168 |
+
<input type="radio" id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-ssl"
|
169 |
+
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][encryption]" value="ssl"
|
170 |
+
<?php echo $this->options->is_const_defined( $this->get_slug(), 'encryption' ) ? 'disabled' : ''; ?>
|
171 |
+
<?php checked( 'ssl', $this->options->get( $this->get_slug(), 'encryption' ) ); ?>
|
172 |
+
/>
|
173 |
+
<?php esc_html_e( 'SSL', 'wp-mail-smtp' ); ?>
|
174 |
+
</label>
|
175 |
+
|
176 |
+
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-tls">
|
177 |
+
<input type="radio" id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-tls"
|
178 |
+
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][encryption]" value="tls"
|
179 |
+
<?php echo $this->options->is_const_defined( $this->get_slug(), 'encryption' ) ? 'disabled' : ''; ?>
|
180 |
+
<?php checked( 'tls', $this->options->get( $this->get_slug(), 'encryption' ) ); ?>
|
181 |
+
/>
|
182 |
+
<?php esc_html_e( 'TLS', 'wp-mail-smtp' ); ?>
|
183 |
+
</label>
|
184 |
+
|
185 |
+
<p class="desc">
|
186 |
+
<?php esc_html_e( 'For most servers TLS is the recommended option. If your SMTP provider offers both SSL and TLS options, we recommend using TLS.', 'wp-mail-smtp' ); ?>
|
187 |
+
</p>
|
188 |
+
</div>
|
189 |
+
</div>
|
190 |
+
|
191 |
+
<!-- PHPMailer SMTPAutoTLS -->
|
192 |
+
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-autotls" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox-toggle wp-mail-smtp-clear <?php echo $this->options->is_const_defined( $this->get_slug(), 'encryption' ) || 'tls' === $this->options->get( $this->get_slug(), 'encryption' ) ? 'inactive' : ''; ?>">
|
193 |
+
<div class="wp-mail-smtp-setting-label">
|
194 |
+
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-autotls"><?php esc_html_e( 'Auto TLS', 'wp-mail-smtp' ); ?></label>
|
195 |
+
</div>
|
196 |
+
<div class="wp-mail-smtp-setting-field">
|
197 |
+
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-autotls">
|
198 |
+
<input type="checkbox" id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-autotls"
|
199 |
+
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][autotls]" value="yes"
|
200 |
+
<?php echo $this->options->is_const_defined( $this->get_slug(), 'autotls' ) ? 'disabled' : ''; ?>
|
201 |
+
<?php checked( true, $this->options->get( $this->get_slug(), 'autotls' ) ); ?>
|
202 |
+
/>
|
203 |
+
<span class="wp-mail-smtp-setting-toggle-switch"></span>
|
204 |
+
<span class="wp-mail-smtp-setting-toggle-checked-label"><?php esc_html_e( 'On', 'wp-mail-smtp' ); ?></span>
|
205 |
+
<span class="wp-mail-smtp-setting-toggle-unchecked-label"><?php esc_html_e( 'Off', 'wp-mail-smtp' ); ?></span>
|
206 |
+
</label>
|
207 |
+
<p class="desc">
|
208 |
+
<?php esc_html_e( 'By default TLS encryption is automatically used if the server supports it, which is recommended. In some cases, due to server misconfigurations, this can cause issues and may need to be disabled.', 'wp-mail-smtp' ); ?>
|
209 |
+
</p>
|
210 |
+
</div>
|
211 |
+
</div>
|
212 |
+
|
213 |
+
<!-- SMTP Authentication -->
|
214 |
+
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-auth" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox-toggle wp-mail-smtp-clear">
|
215 |
+
<div class="wp-mail-smtp-setting-label">
|
216 |
+
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-auth"><?php esc_html_e( 'Authentication', 'wp-mail-smtp' ); ?></label>
|
217 |
+
</div>
|
218 |
+
<div class="wp-mail-smtp-setting-field">
|
219 |
+
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-auth">
|
220 |
+
<input type="checkbox" id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-auth"
|
221 |
+
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][auth]" value="yes"
|
222 |
+
<?php echo $this->options->is_const_defined( $this->get_slug(), 'auth' ) ? 'disabled' : ''; ?>
|
223 |
+
<?php checked( true, $this->options->get( $this->get_slug(), 'auth' ) ); ?>
|
224 |
+
/>
|
225 |
+
<span class="wp-mail-smtp-setting-toggle-switch"></span>
|
226 |
+
<span class="wp-mail-smtp-setting-toggle-checked-label"><?php esc_html_e( 'On', 'wp-mail-smtp' ); ?></span>
|
227 |
+
<span class="wp-mail-smtp-setting-toggle-unchecked-label"><?php esc_html_e( 'Off', 'wp-mail-smtp' ); ?></span>
|
228 |
+
</label>
|
229 |
+
</div>
|
230 |
+
</div>
|
231 |
+
|
232 |
+
<!-- SMTP Username -->
|
233 |
+
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-user" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear <?php echo ! $this->options->is_const_defined( $this->get_slug(), 'auth' ) && ! $this->options->get( $this->get_slug(), 'auth' ) ? 'inactive' : ''; ?>">
|
234 |
+
<div class="wp-mail-smtp-setting-label">
|
235 |
+
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-user"><?php esc_html_e( 'SMTP Username', 'wp-mail-smtp' ); ?></label>
|
236 |
+
</div>
|
237 |
+
<div class="wp-mail-smtp-setting-field">
|
238 |
+
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][user]" type="text"
|
239 |
+
value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'user' ) ); ?>"
|
240 |
+
<?php echo $this->options->is_const_defined( $this->get_slug(), 'user' ) ? 'disabled' : ''; ?>
|
241 |
+
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-user" spellcheck="false" autocomplete="off"
|
242 |
+
/>
|
243 |
+
</div>
|
244 |
+
</div>
|
245 |
+
|
246 |
+
<!-- SMTP Password -->
|
247 |
+
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-pass" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-password wp-mail-smtp-clear <?php echo ! $this->options->is_const_defined( $this->get_slug(), 'auth' ) && ! $this->options->get( $this->get_slug(), 'auth' ) ? 'inactive' : ''; ?>">
|
248 |
+
<div class="wp-mail-smtp-setting-label">
|
249 |
+
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-pass"><?php esc_html_e( 'SMTP Password', 'wp-mail-smtp' ); ?></label>
|
250 |
+
</div>
|
251 |
+
<div class="wp-mail-smtp-setting-field">
|
252 |
+
<?php if ( $this->options->is_const_defined( $this->get_slug(), 'pass' ) ) : ?>
|
253 |
+
<input type="text" value="*************" disabled id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-pass"/>
|
254 |
+
<?php else : ?>
|
255 |
+
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][pass]" type="password"
|
256 |
+
value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'pass' ) ); ?>"
|
257 |
+
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-pass" spellcheck="false" autocomplete="off"
|
258 |
+
/>
|
259 |
+
<p class="desc">
|
260 |
+
<?php
|
261 |
+
printf(
|
262 |
+
/* translators: %s - wp-config.php. */
|
263 |
+
esc_html__( 'The password is stored in plain text. We highly recommend you setup your password in your WordPress configuration file for improved security; to do this add the lines below to your %s file.', 'wp-mail-smtp' ),
|
264 |
+
'<code>wp-config.php</code>'
|
265 |
+
);
|
266 |
+
?>
|
267 |
+
</p>
|
268 |
+
<pre>
|
269 |
+
define( 'WPMS_ON', true );
|
270 |
+
define( 'WPMS_SMTP_PASS', 'your_password' );
|
271 |
+
</pre>
|
272 |
+
<?php endif; ?>
|
273 |
+
</div>
|
274 |
+
</div>
|
275 |
+
|
276 |
+
<?php
|
277 |
+
}
|
278 |
+
|
279 |
+
/**
|
280 |
+
* Check whether we can use this provider based on the PHP version.
|
281 |
+
* Valid for those, that use SDK.
|
282 |
+
*
|
283 |
+
* @return bool
|
284 |
+
*/
|
285 |
+
protected function is_php_correct() {
|
286 |
+
return version_compare( phpversion(), $this->php, '>=' );
|
287 |
+
}
|
288 |
+
|
289 |
+
/**
|
290 |
+
* Display a helpful message to those users, that are using an outdated version of PHP,
|
291 |
+
* which is not supported by the currently selected Provider.
|
292 |
+
*/
|
293 |
+
protected function display_php_warning() {
|
294 |
+
?>
|
295 |
+
|
296 |
+
<blockquote>
|
297 |
+
<?php
|
298 |
+
printf(
|
299 |
+
/* translators: %1$s - Provider name; %2$s - PHP version required by Provider; %3$s - current PHP version. */
|
300 |
+
esc_html__( '%1$s requires PHP %2$s to work and does not support your current PHP version %3$s. Please contact your host and request a PHP upgrade to the latest one.', 'wp-mail-smtp' ),
|
301 |
+
$this->title,
|
302 |
+
$this->php,
|
303 |
+
phpversion()
|
304 |
+
)
|
305 |
+
?>
|
306 |
+
<br>
|
307 |
+
<?php esc_html_e( 'Meanwhile you can switch to the "Other SMTP" Mailer option.', 'wp-mail-smtp' ); ?>
|
308 |
+
</blockquote>
|
309 |
+
|
310 |
+
<?php
|
311 |
+
}
|
312 |
+
}
|
src/Providers/OptionInterface.php
CHANGED
@@ -1,64 +1,64 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Providers;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Interface ProviderInterface, shared between all current and future providers.
|
7 |
-
* Defines required methods across all providers.
|
8 |
-
*
|
9 |
-
* @since 1.0.0
|
10 |
-
*/
|
11 |
-
interface OptionInterface {
|
12 |
-
|
13 |
-
/**
|
14 |
-
* Get the mailer provider slug.
|
15 |
-
*
|
16 |
-
* @since 1.0.0
|
17 |
-
*
|
18 |
-
* @return string
|
19 |
-
*/
|
20 |
-
public function get_slug();
|
21 |
-
|
22 |
-
/**
|
23 |
-
* Get the mailer provider title (or name).
|
24 |
-
*
|
25 |
-
* @since 1.0.0
|
26 |
-
*
|
27 |
-
* @return string
|
28 |
-
*/
|
29 |
-
public function get_title();
|
30 |
-
|
31 |
-
/**
|
32 |
-
* Get the mailer provider description.
|
33 |
-
*
|
34 |
-
* @since 1.0.0
|
35 |
-
*
|
36 |
-
* @return string
|
37 |
-
*/
|
38 |
-
public function get_description();
|
39 |
-
|
40 |
-
/**
|
41 |
-
* Get the mailer provider minimum PHP version.
|
42 |
-
*
|
43 |
-
* @since 1.0.0
|
44 |
-
*
|
45 |
-
* @return string
|
46 |
-
*/
|
47 |
-
public function get_php_version();
|
48 |
-
|
49 |
-
/**
|
50 |
-
* Get the mailer provider logo URL.
|
51 |
-
*
|
52 |
-
* @since 1.0.0
|
53 |
-
*
|
54 |
-
* @return string
|
55 |
-
*/
|
56 |
-
public function get_logo_url();
|
57 |
-
|
58 |
-
/**
|
59 |
-
* Output the mailer provider options.
|
60 |
-
*
|
61 |
-
* @since 1.0.0
|
62 |
-
*/
|
63 |
-
public function display_options();
|
64 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Providers;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Interface ProviderInterface, shared between all current and future providers.
|
7 |
+
* Defines required methods across all providers.
|
8 |
+
*
|
9 |
+
* @since 1.0.0
|
10 |
+
*/
|
11 |
+
interface OptionInterface {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Get the mailer provider slug.
|
15 |
+
*
|
16 |
+
* @since 1.0.0
|
17 |
+
*
|
18 |
+
* @return string
|
19 |
+
*/
|
20 |
+
public function get_slug();
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Get the mailer provider title (or name).
|
24 |
+
*
|
25 |
+
* @since 1.0.0
|
26 |
+
*
|
27 |
+
* @return string
|
28 |
+
*/
|
29 |
+
public function get_title();
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Get the mailer provider description.
|
33 |
+
*
|
34 |
+
* @since 1.0.0
|
35 |
+
*
|
36 |
+
* @return string
|
37 |
+
*/
|
38 |
+
public function get_description();
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Get the mailer provider minimum PHP version.
|
42 |
+
*
|
43 |
+
* @since 1.0.0
|
44 |
+
*
|
45 |
+
* @return string
|
46 |
+
*/
|
47 |
+
public function get_php_version();
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Get the mailer provider logo URL.
|
51 |
+
*
|
52 |
+
* @since 1.0.0
|
53 |
+
*
|
54 |
+
* @return string
|
55 |
+
*/
|
56 |
+
public function get_logo_url();
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Output the mailer provider options.
|
60 |
+
*
|
61 |
+
* @since 1.0.0
|
62 |
+
*/
|
63 |
+
public function display_options();
|
64 |
+
}
|
src/Providers/Pepipost/Options.php
CHANGED
@@ -1,29 +1,29 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Providers\Pepipost;
|
4 |
-
|
5 |
-
use WPMailSMTP\Providers\OptionAbstract;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Class Option.
|
9 |
-
*
|
10 |
-
* @since 1.0.0
|
11 |
-
*/
|
12 |
-
class Option extends OptionAbstract {
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Pepipost constructor.
|
16 |
-
*
|
17 |
-
* @since 1.0.0
|
18 |
-
*/
|
19 |
-
public function __construct() {
|
20 |
-
|
21 |
-
parent::__construct(
|
22 |
-
array(
|
23 |
-
'logo_url' => wp_mail_smtp()->plugin_url . '/assets/images/pepipost.png',
|
24 |
-
'slug' => 'pepipost',
|
25 |
-
'title' => esc_html__( 'Pepipost', 'wp-mail-smtp' ),
|
26 |
-
)
|
27 |
-
);
|
28 |
-
}
|
29 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Providers\Pepipost;
|
4 |
+
|
5 |
+
use WPMailSMTP\Providers\OptionAbstract;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class Option.
|
9 |
+
*
|
10 |
+
* @since 1.0.0
|
11 |
+
*/
|
12 |
+
class Option extends OptionAbstract {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Pepipost constructor.
|
16 |
+
*
|
17 |
+
* @since 1.0.0
|
18 |
+
*/
|
19 |
+
public function __construct() {
|
20 |
+
|
21 |
+
parent::__construct(
|
22 |
+
array(
|
23 |
+
'logo_url' => wp_mail_smtp()->plugin_url . '/assets/images/pepipost.png',
|
24 |
+
'slug' => 'pepipost',
|
25 |
+
'title' => esc_html__( 'Pepipost', 'wp-mail-smtp' ),
|
26 |
+
)
|
27 |
+
);
|
28 |
+
}
|
29 |
+
}
|
src/Providers/SMTP/Options.php
CHANGED
@@ -1,45 +1,45 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Providers\SMTP;
|
4 |
-
|
5 |
-
use WPMailSMTP\Providers\OptionAbstract;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Class SMTP.
|
9 |
-
*
|
10 |
-
* @since 1.0.0
|
11 |
-
*/
|
12 |
-
class Options extends OptionAbstract {
|
13 |
-
|
14 |
-
/**
|
15 |
-
* SMTP constructor.
|
16 |
-
*
|
17 |
-
* @since 1.0.0
|
18 |
-
*/
|
19 |
-
public function __construct() {
|
20 |
-
|
21 |
-
parent::__construct(
|
22 |
-
array(
|
23 |
-
'logo_url' => wp_mail_smtp()->plugin_url . '/assets/images/smtp.png',
|
24 |
-
'slug' => 'smtp',
|
25 |
-
'title' => esc_html__( 'Other SMTP', 'wp-mail-smtp' ),
|
26 |
-
/* translators: %1$s - opening link tag; %2$s - closing link tag. */
|
27 |
-
'description' => sprintf(
|
28 |
-
wp_kses(
|
29 |
-
__( 'Use the SMTP details provided by your hosting provider or email service.<br><br>To see recommended settings for the popular services as well as troubleshooting tips, check out our %1$sSMTP documentation%2$s.', 'wp-mail-smtp' ),
|
30 |
-
array(
|
31 |
-
'br' => array(),
|
32 |
-
'a' => array(
|
33 |
-
'href' => array(),
|
34 |
-
'rel' => array(),
|
35 |
-
'target' => array(),
|
36 |
-
),
|
37 |
-
)
|
38 |
-
),
|
39 |
-
'<a href="https://wpforms.com/docs/how-to-set-up-smtp-using-the-wp-mail-smtp-plugin/" target="_blank" rel="noopener noreferrer">',
|
40 |
-
'</a>'
|
41 |
-
),
|
42 |
-
)
|
43 |
-
);
|
44 |
-
}
|
45 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Providers\SMTP;
|
4 |
+
|
5 |
+
use WPMailSMTP\Providers\OptionAbstract;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class SMTP.
|
9 |
+
*
|
10 |
+
* @since 1.0.0
|
11 |
+
*/
|
12 |
+
class Options extends OptionAbstract {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* SMTP constructor.
|
16 |
+
*
|
17 |
+
* @since 1.0.0
|
18 |
+
*/
|
19 |
+
public function __construct() {
|
20 |
+
|
21 |
+
parent::__construct(
|
22 |
+
array(
|
23 |
+
'logo_url' => wp_mail_smtp()->plugin_url . '/assets/images/smtp.png',
|
24 |
+
'slug' => 'smtp',
|
25 |
+
'title' => esc_html__( 'Other SMTP', 'wp-mail-smtp' ),
|
26 |
+
/* translators: %1$s - opening link tag; %2$s - closing link tag. */
|
27 |
+
'description' => sprintf(
|
28 |
+
wp_kses(
|
29 |
+
__( 'Use the SMTP details provided by your hosting provider or email service.<br><br>To see recommended settings for the popular services as well as troubleshooting tips, check out our %1$sSMTP documentation%2$s.', 'wp-mail-smtp' ),
|
30 |
+
array(
|
31 |
+
'br' => array(),
|
32 |
+
'a' => array(
|
33 |
+
'href' => array(),
|
34 |
+
'rel' => array(),
|
35 |
+
'target' => array(),
|
36 |
+
),
|
37 |
+
)
|
38 |
+
),
|
39 |
+
'<a href="https://wpforms.com/docs/how-to-set-up-smtp-using-the-wp-mail-smtp-plugin/" target="_blank" rel="noopener noreferrer">',
|
40 |
+
'</a>'
|
41 |
+
),
|
42 |
+
)
|
43 |
+
);
|
44 |
+
}
|
45 |
+
}
|
src/Providers/Sendgrid/Mailer.php
CHANGED
@@ -1,294 +1,294 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Providers\Sendgrid;
|
4 |
-
|
5 |
-
use WPMailSMTP\Providers\MailerAbstract;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Class Mailer.
|
9 |
-
*
|
10 |
-
* @since 1.0.0
|
11 |
-
*/
|
12 |
-
class Mailer extends MailerAbstract {
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Which response code from HTTP provider is considered to be successful?
|
16 |
-
*
|
17 |
-
* @var int
|
18 |
-
*/
|
19 |
-
protected $email_sent_code = 202;
|
20 |
-
|
21 |
-
/**
|
22 |
-
* URL to make an API request to.
|
23 |
-
*
|
24 |
-
* @var string
|
25 |
-
*/
|
26 |
-
protected $url = 'https://api.sendgrid.com/v3/mail/send';
|
27 |
-
|
28 |
-
/**
|
29 |
-
* Mailer constructor.
|
30 |
-
*
|
31 |
-
* @since 1.0.0
|
32 |
-
*
|
33 |
-
* @param \PHPMailer $phpmailer
|
34 |
-
*/
|
35 |
-
public function __construct( $phpmailer ) {
|
36 |
-
|
37 |
-
// We want to prefill everything from \PHPMailer class.
|
38 |
-
parent::__construct( $phpmailer );
|
39 |
-
|
40 |
-
$this->set_header( 'Authorization', 'Bearer ' . $this->options->get( $this->mailer, 'api_key' ) );
|
41 |
-
$this->set_header( 'content-type', 'application/json' );
|
42 |
-
}
|
43 |
-
|
44 |
-
/**
|
45 |
-
* Redefine the way email body is returned.
|
46 |
-
* By default we are sending an array of data.
|
47 |
-
* SendGrid requires a JSON, so we encode the body.
|
48 |
-
*
|
49 |
-
* @since 1.0.0
|
50 |
-
*/
|
51 |
-
public function get_body() {
|
52 |
-
|
53 |
-
$body = parent::get_body();
|
54 |
-
|
55 |
-
return wp_json_encode( $body );
|
56 |
-
}
|
57 |
-
|
58 |
-
/**
|
59 |
-
* @inheritdoc
|
60 |
-
*/
|
61 |
-
public function set_from( $email, $name = '' ) {
|
62 |
-
|
63 |
-
if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
|
64 |
-
return;
|
65 |
-
}
|
66 |
-
|
67 |
-
$from['email'] = $email;
|
68 |
-
|
69 |
-
if ( ! empty( $name ) ) {
|
70 |
-
$from['name'] = $name;
|
71 |
-
}
|
72 |
-
|
73 |
-
$this->set_body_param(
|
74 |
-
array(
|
75 |
-
'from' => $from,
|
76 |
-
)
|
77 |
-
);
|
78 |
-
}
|
79 |
-
|
80 |
-
/**
|
81 |
-
* @inheritdoc
|
82 |
-
*/
|
83 |
-
public function set_recipients( $recipients ) {
|
84 |
-
|
85 |
-
if ( empty( $recipients ) ) {
|
86 |
-
return;
|
87 |
-
}
|
88 |
-
|
89 |
-
// Allow for now only these recipient types.
|
90 |
-
$default = array( 'to', 'cc', 'bcc' );
|
91 |
-
$data = array();
|
92 |
-
|
93 |
-
foreach ( $recipients as $type => $emails ) {
|
94 |
-
if (
|
95 |
-
! in_array( $type, $default, true ) ||
|
96 |
-
empty( $emails ) ||
|
97 |
-
! is_array( $emails )
|
98 |
-
) {
|
99 |
-
continue;
|
100 |
-
}
|
101 |
-
|
102 |
-
$data[ $type ] = array();
|
103 |
-
|
104 |
-
// Iterate over all emails for each type.
|
105 |
-
// There might be multiple cc/to/bcc emails.
|
106 |
-
foreach ( $emails as $email ) {
|
107 |
-
$holder = array();
|
108 |
-
$addr = isset( $email[0] ) ? $email[0] : false;
|
109 |
-
$name = isset( $email[1] ) ? $email[1] : false;
|
110 |
-
|
111 |
-
if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
|
112 |
-
continue;
|
113 |
-
}
|
114 |
-
|
115 |
-
$holder['email'] = $addr;
|
116 |
-
if ( ! empty( $name ) ) {
|
117 |
-
$holder['name'] = $name;
|
118 |
-
}
|
119 |
-
|
120 |
-
array_push( $data[ $type ], $holder );
|
121 |
-
}
|
122 |
-
}
|
123 |
-
|
124 |
-
if ( ! empty( $data ) ) {
|
125 |
-
$this->set_body_param(
|
126 |
-
array(
|
127 |
-
'personalizations' => array( $data ),
|
128 |
-
)
|
129 |
-
);
|
130 |
-
}
|
131 |
-
}
|
132 |
-
|
133 |
-
/**
|
134 |
-
* @inheritdoc
|
135 |
-
*/
|
136 |
-
public function set_content( $content ) {
|
137 |
-
|
138 |
-
if ( empty( $content ) ) {
|
139 |
-
return;
|
140 |
-
}
|
141 |
-
|
142 |
-
if ( is_array( $content ) ) {
|
143 |
-
|
144 |
-
$default = array( 'text', 'html' );
|
145 |
-
$data = array();
|
146 |
-
|
147 |
-
foreach ( $content as $type => $body ) {
|
148 |
-
if (
|
149 |
-
! in_array( $type, $default, true ) ||
|
150 |
-
empty( $body )
|
151 |
-
) {
|
152 |
-
continue;
|
153 |
-
}
|
154 |
-
|
155 |
-
$content_type = 'text/plain';
|
156 |
-
$content_value = $body;
|
157 |
-
|
158 |
-
if ( $type === 'html' ) {
|
159 |
-
$content_type = 'text/html';
|
160 |
-
}
|
161 |
-
|
162 |
-
$data[] = array(
|
163 |
-
'type' => $content_type,
|
164 |
-
'value' => $content_value,
|
165 |
-
);
|
166 |
-
}
|
167 |
-
|
168 |
-
$this->set_body_param(
|
169 |
-
array(
|
170 |
-
'content' => $data,
|
171 |
-
)
|
172 |
-
);
|
173 |
-
} else {
|
174 |
-
$data['type'] = 'text/plain';
|
175 |
-
$data['value'] = $content;
|
176 |
-
|
177 |
-
if ( $this->phpmailer->ContentType === 'text/html' ) {
|
178 |
-
$data['type'] = 'text/html';
|
179 |
-
}
|
180 |
-
|
181 |
-
$this->set_body_param(
|
182 |
-
array(
|
183 |
-
'content' => array( $data ),
|
184 |
-
)
|
185 |
-
);
|
186 |
-
}
|
187 |
-
}
|
188 |
-
|
189 |
-
/**
|
190 |
-
* SendGrid accepts an array of files content in body, so we will include all files and send.
|
191 |
-
* Doesn't handle exceeding the limits etc, as this is done and reported be SendGrid API.
|
192 |
-
*
|
193 |
-
* @since 1.0.0
|
194 |
-
*
|
195 |
-
* @param array $attachments
|
196 |
-
*/
|
197 |
-
public function set_attachments( $attachments ) {
|
198 |
-
|
199 |
-
if ( empty( $attachments ) ) {
|
200 |
-
return;
|
201 |
-
}
|
202 |
-
|
203 |
-
$data = array();
|
204 |
-
|
205 |
-
foreach ( $attachments as $attachment ) {
|
206 |
-
$file = false;
|
207 |
-
|
208 |
-
/*
|
209 |
-
* We are not using WP_Filesystem API as we can't reliably work with it.
|
210 |
-
* It is not always available, same as credentials for FTP.
|
211 |
-
*/
|
212 |
-
try {
|
213 |
-
if ( is_file( $attachment[0] ) && is_readable( $attachment[0] ) ) {
|
214 |
-
$file = file_get_contents( $attachment[0] );
|
215 |
-
}
|
216 |
-
} catch ( \Exception $e ) {
|
217 |
-
$file = false;
|
218 |
-
}
|
219 |
-
|
220 |
-
if ( $file === false ) {
|
221 |
-
continue;
|
222 |
-
}
|
223 |
-
|
224 |
-
$data[] = array(
|
225 |
-
'content' => base64_encode( $file ),
|
226 |
-
'type' => $attachment[4],
|
227 |
-
'filename' => $attachment[1],
|
228 |
-
'disposition' => $attachment[6],
|
229 |
-
);
|
230 |
-
}
|
231 |
-
|
232 |
-
if ( ! empty( $data ) ) {
|
233 |
-
$this->set_body_param(
|
234 |
-
array(
|
235 |
-
'attachments' => $data,
|
236 |
-
)
|
237 |
-
);
|
238 |
-
}
|
239 |
-
}
|
240 |
-
|
241 |
-
/**
|
242 |
-
* @inheritdoc
|
243 |
-
*/
|
244 |
-
public function set_reply_to( $reply_to ) {
|
245 |
-
|
246 |
-
if ( empty( $reply_to ) ) {
|
247 |
-
return;
|
248 |
-
}
|
249 |
-
|
250 |
-
$data = array();
|
251 |
-
|
252 |
-
foreach ( $reply_to as $key => $emails ) {
|
253 |
-
if (
|
254 |
-
empty( $emails ) ||
|
255 |
-
! is_array( $emails )
|
256 |
-
) {
|
257 |
-
continue;
|
258 |
-
}
|
259 |
-
|
260 |
-
$addr = isset( $emails[0] ) ? $emails[0] : false;
|
261 |
-
$name = isset( $emails[1] ) ? $emails[1] : false;
|
262 |
-
|
263 |
-
if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
|
264 |
-
continue;
|
265 |
-
}
|
266 |
-
|
267 |
-
$data['email'] = $addr;
|
268 |
-
if ( ! empty( $name ) ) {
|
269 |
-
$data['name'] = $name;
|
270 |
-
}
|
271 |
-
|
272 |
-
break;
|
273 |
-
}
|
274 |
-
|
275 |
-
if ( ! empty( $data ) ) {
|
276 |
-
$this->set_body_param(
|
277 |
-
array(
|
278 |
-
'reply_to' => $data,
|
279 |
-
)
|
280 |
-
);
|
281 |
-
}
|
282 |
-
}
|
283 |
-
|
284 |
-
/**
|
285 |
-
* SendGrid doesn't support sender or return_path params.
|
286 |
-
* So we do nothing.
|
287 |
-
*
|
288 |
-
* @since 1.0.0
|
289 |
-
*
|
290 |
-
* @param string $email
|
291 |
-
*/
|
292 |
-
public function set_return_path( $email ) {
|
293 |
-
}
|
294 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Providers\Sendgrid;
|
4 |
+
|
5 |
+
use WPMailSMTP\Providers\MailerAbstract;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class Mailer.
|
9 |
+
*
|
10 |
+
* @since 1.0.0
|
11 |
+
*/
|
12 |
+
class Mailer extends MailerAbstract {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Which response code from HTTP provider is considered to be successful?
|
16 |
+
*
|
17 |
+
* @var int
|
18 |
+
*/
|
19 |
+
protected $email_sent_code = 202;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* URL to make an API request to.
|
23 |
+
*
|
24 |
+
* @var string
|
25 |
+
*/
|
26 |
+
protected $url = 'https://api.sendgrid.com/v3/mail/send';
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Mailer constructor.
|
30 |
+
*
|
31 |
+
* @since 1.0.0
|
32 |
+
*
|
33 |
+
* @param \PHPMailer $phpmailer
|
34 |
+
*/
|
35 |
+
public function __construct( $phpmailer ) {
|
36 |
+
|
37 |
+
// We want to prefill everything from \PHPMailer class.
|
38 |
+
parent::__construct( $phpmailer );
|
39 |
+
|
40 |
+
$this->set_header( 'Authorization', 'Bearer ' . $this->options->get( $this->mailer, 'api_key' ) );
|
41 |
+
$this->set_header( 'content-type', 'application/json' );
|
42 |
+
}
|
43 |
+
|
44 |
+
/**
|
45 |
+
* Redefine the way email body is returned.
|
46 |
+
* By default we are sending an array of data.
|
47 |
+
* SendGrid requires a JSON, so we encode the body.
|
48 |
+
*
|
49 |
+
* @since 1.0.0
|
50 |
+
*/
|
51 |
+
public function get_body() {
|
52 |
+
|
53 |
+
$body = parent::get_body();
|
54 |
+
|
55 |
+
return wp_json_encode( $body );
|
56 |
+
}
|
57 |
+
|
58 |
+
/**
|
59 |
+
* @inheritdoc
|
60 |
+
*/
|
61 |
+
public function set_from( $email, $name = '' ) {
|
62 |
+
|
63 |
+
if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
|
64 |
+
return;
|
65 |
+
}
|
66 |
+
|
67 |
+
$from['email'] = $email;
|
68 |
+
|
69 |
+
if ( ! empty( $name ) ) {
|
70 |
+
$from['name'] = $name;
|
71 |
+
}
|
72 |
+
|
73 |
+
$this->set_body_param(
|
74 |
+
array(
|
75 |
+
'from' => $from,
|
76 |
+
)
|
77 |
+
);
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* @inheritdoc
|
82 |
+
*/
|
83 |
+
public function set_recipients( $recipients ) {
|
84 |
+
|
85 |
+
if ( empty( $recipients ) ) {
|
86 |
+
return;
|
87 |
+
}
|
88 |
+
|
89 |
+
// Allow for now only these recipient types.
|
90 |
+
$default = array( 'to', 'cc', 'bcc' );
|
91 |
+
$data = array();
|
92 |
+
|
93 |
+
foreach ( $recipients as $type => $emails ) {
|
94 |
+
if (
|
95 |
+
! in_array( $type, $default, true ) ||
|
96 |
+
empty( $emails ) ||
|
97 |
+
! is_array( $emails )
|
98 |
+
) {
|
99 |
+
continue;
|
100 |
+
}
|
101 |
+
|
102 |
+
$data[ $type ] = array();
|
103 |
+
|
104 |
+
// Iterate over all emails for each type.
|
105 |
+
// There might be multiple cc/to/bcc emails.
|
106 |
+
foreach ( $emails as $email ) {
|
107 |
+
$holder = array();
|
108 |
+
$addr = isset( $email[0] ) ? $email[0] : false;
|
109 |
+
$name = isset( $email[1] ) ? $email[1] : false;
|
110 |
+
|
111 |
+
if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
|
112 |
+
continue;
|
113 |
+
}
|
114 |
+
|
115 |
+
$holder['email'] = $addr;
|
116 |
+
if ( ! empty( $name ) ) {
|
117 |
+
$holder['name'] = $name;
|
118 |
+
}
|
119 |
+
|
120 |
+
array_push( $data[ $type ], $holder );
|
121 |
+
}
|
122 |
+
}
|
123 |
+
|
124 |
+
if ( ! empty( $data ) ) {
|
125 |
+
$this->set_body_param(
|
126 |
+
array(
|
127 |
+
'personalizations' => array( $data ),
|
128 |
+
)
|
129 |
+
);
|
130 |
+
}
|
131 |
+
}
|
132 |
+
|
133 |
+
/**
|
134 |
+
* @inheritdoc
|
135 |
+
*/
|
136 |
+
public function set_content( $content ) {
|
137 |
+
|
138 |
+
if ( empty( $content ) ) {
|
139 |
+
return;
|
140 |
+
}
|
141 |
+
|
142 |
+
if ( is_array( $content ) ) {
|
143 |
+
|
144 |
+
$default = array( 'text', 'html' );
|
145 |
+
$data = array();
|
146 |
+
|
147 |
+
foreach ( $content as $type => $body ) {
|
148 |
+
if (
|
149 |
+
! in_array( $type, $default, true ) ||
|
150 |
+
empty( $body )
|
151 |
+
) {
|
152 |
+
continue;
|
153 |
+
}
|
154 |
+
|
155 |
+
$content_type = 'text/plain';
|
156 |
+
$content_value = $body;
|
157 |
+
|
158 |
+
if ( $type === 'html' ) {
|
159 |
+
$content_type = 'text/html';
|
160 |
+
}
|
161 |
+
|
162 |
+
$data[] = array(
|
163 |
+
'type' => $content_type,
|
164 |
+
'value' => $content_value,
|
165 |
+
);
|
166 |
+
}
|
167 |
+
|
168 |
+
$this->set_body_param(
|
169 |
+
array(
|
170 |
+
'content' => $data,
|
171 |
+
)
|
172 |
+
);
|
173 |
+
} else {
|
174 |
+
$data['type'] = 'text/plain';
|
175 |
+
$data['value'] = $content;
|
176 |
+
|
177 |
+
if ( $this->phpmailer->ContentType === 'text/html' ) {
|
178 |
+
$data['type'] = 'text/html';
|
179 |
+
}
|
180 |
+
|
181 |
+
$this->set_body_param(
|
182 |
+
array(
|
183 |
+
'content' => array( $data ),
|
184 |
+
)
|
185 |
+
);
|
186 |
+
}
|
187 |
+
}
|
188 |
+
|
189 |
+
/**
|
190 |
+
* SendGrid accepts an array of files content in body, so we will include all files and send.
|
191 |
+
* Doesn't handle exceeding the limits etc, as this is done and reported be SendGrid API.
|
192 |
+
*
|
193 |
+
* @since 1.0.0
|
194 |
+
*
|
195 |
+
* @param array $attachments
|
196 |
+
*/
|
197 |
+
public function set_attachments( $attachments ) {
|
198 |
+
|
199 |
+
if ( empty( $attachments ) ) {
|
200 |
+
return;
|
201 |
+
}
|
202 |
+
|
203 |
+
$data = array();
|
204 |
+
|
205 |
+
foreach ( $attachments as $attachment ) {
|
206 |
+
$file = false;
|
207 |
+
|
208 |
+
/*
|
209 |
+
* We are not using WP_Filesystem API as we can't reliably work with it.
|
210 |
+
* It is not always available, same as credentials for FTP.
|
211 |
+
*/
|
212 |
+
try {
|
213 |
+
if ( is_file( $attachment[0] ) && is_readable( $attachment[0] ) ) {
|
214 |
+
$file = file_get_contents( $attachment[0] );
|
215 |
+
}
|
216 |
+
} catch ( \Exception $e ) {
|
217 |
+
$file = false;
|
218 |
+
}
|
219 |
+
|
220 |
+
if ( $file === false ) {
|
221 |
+
continue;
|
222 |
+
}
|
223 |
+
|
224 |
+
$data[] = array(
|
225 |
+
'content' => base64_encode( $file ),
|
226 |
+
'type' => $attachment[4],
|
227 |
+
'filename' => $attachment[1],
|
228 |
+
'disposition' => $attachment[6],
|
229 |
+
);
|
230 |
+
}
|
231 |
+
|
232 |
+
if ( ! empty( $data ) ) {
|
233 |
+
$this->set_body_param(
|
234 |
+
array(
|
235 |
+
'attachments' => $data,
|
236 |
+
)
|
237 |
+
);
|
238 |
+
}
|
239 |
+
}
|
240 |
+
|
241 |
+
/**
|
242 |
+
* @inheritdoc
|
243 |
+
*/
|
244 |
+
public function set_reply_to( $reply_to ) {
|
245 |
+
|
246 |
+
if ( empty( $reply_to ) ) {
|
247 |
+
return;
|
248 |
+
}
|
249 |
+
|
250 |
+
$data = array();
|
251 |
+
|
252 |
+
foreach ( $reply_to as $key => $emails ) {
|
253 |
+
if (
|
254 |
+
empty( $emails ) ||
|
255 |
+
! is_array( $emails )
|
256 |
+
) {
|
257 |
+
continue;
|
258 |
+
}
|
259 |
+
|
260 |
+
$addr = isset( $emails[0] ) ? $emails[0] : false;
|
261 |
+
$name = isset( $emails[1] ) ? $emails[1] : false;
|
262 |
+
|
263 |
+
if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
|
264 |
+
continue;
|
265 |
+
}
|
266 |
+
|
267 |
+
$data['email'] = $addr;
|
268 |
+
if ( ! empty( $name ) ) {
|
269 |
+
$data['name'] = $name;
|
270 |
+
}
|
271 |
+
|
272 |
+
break;
|
273 |
+
}
|
274 |
+
|
275 |
+
if ( ! empty( $data ) ) {
|
276 |
+
$this->set_body_param(
|
277 |
+
array(
|
278 |
+
'reply_to' => $data,
|
279 |
+
)
|
280 |
+
);
|
281 |
+
}
|
282 |
+
}
|
283 |
+
|
284 |
+
/**
|
285 |
+
* SendGrid doesn't support sender or return_path params.
|
286 |
+
* So we do nothing.
|
287 |
+
*
|
288 |
+
* @since 1.0.0
|
289 |
+
*
|
290 |
+
* @param string $email
|
291 |
+
*/
|
292 |
+
public function set_return_path( $email ) {
|
293 |
+
}
|
294 |
+
}
|
src/Providers/Sendgrid/Options.php
CHANGED
@@ -1,89 +1,89 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP\Providers\Sendgrid;
|
4 |
-
|
5 |
-
use WPMailSMTP\Providers\OptionAbstract;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Class Option.
|
9 |
-
*
|
10 |
-
* @since 1.0.0
|
11 |
-
*/
|
12 |
-
class Options extends OptionAbstract {
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Options constructor.
|
16 |
-
*
|
17 |
-
* @since 1.0.0
|
18 |
-
*/
|
19 |
-
public function __construct() {
|
20 |
-
|
21 |
-
parent::__construct(
|
22 |
-
array(
|
23 |
-
'logo_url' => wp_mail_smtp()->plugin_url . '/assets/images/sendgrid.png',
|
24 |
-
'slug' => 'sendgrid',
|
25 |
-
'title' => esc_html__( 'SendGrid', 'wp-mail-smtp' ),
|
26 |
-
'description' => sprintf(
|
27 |
-
wp_kses(
|
28 |
-
/* translators: %1$s - opening link tag; %2$s - closing link tag; %3$s - opening link tag; %4$s - closing link tag. */
|
29 |
-
__( '%1$sSendGrid%2$s is one of the leading transactional email services, sending over 35 billion emails every month. They provide users 100 free emails per month.<br><br>Read our %3$sSendGrid documentation%4$s to learn how to set up SendGrid and improve your email deliverability.', 'wp-mail-smtp' ),
|
30 |
-
array(
|
31 |
-
'br' => array(),
|
32 |
-
'a' => array(
|
33 |
-
'href' => array(),
|
34 |
-
'rel' => array(),
|
35 |
-
'target' => array(),
|
36 |
-
),
|
37 |
-
)
|
38 |
-
),
|
39 |
-
'<a href="https://sendgrid.com" target="_blank" rel="noopener noreferrer">',
|
40 |
-
'</a>',
|
41 |
-
'<a href="https://wpforms.com/fix-wordpress-email-notifications-with-sendgrid/" target="_blank" rel="noopener noreferrer">',
|
42 |
-
'</a>'
|
43 |
-
),
|
44 |
-
)
|
45 |
-
);
|
46 |
-
}
|
47 |
-
|
48 |
-
/**
|
49 |
-
* @inheritdoc
|
50 |
-
*/
|
51 |
-
public function display_options() {
|
52 |
-
?>
|
53 |
-
|
54 |
-
<!-- API Key -->
|
55 |
-
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-api_key" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
56 |
-
<div class="wp-mail-smtp-setting-label">
|
57 |
-
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"><?php esc_html_e( 'API Key', 'wp-mail-smtp' ); ?></label>
|
58 |
-
</div>
|
59 |
-
<div class="wp-mail-smtp-setting-field">
|
60 |
-
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][api_key]" type="text"
|
61 |
-
value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'api_key' ) ); ?>"
|
62 |
-
<?php echo $this->options->is_const_defined( $this->get_slug(), 'api_key' ) ? 'disabled' : ''; ?>
|
63 |
-
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key" spellcheck="false"
|
64 |
-
/>
|
65 |
-
<p class="desc">
|
66 |
-
<?php
|
67 |
-
printf(
|
68 |
-
/* translators: %s - API key link. */
|
69 |
-
esc_html__( 'Follow this link to get an API Key from SendGrid: %s.', 'wp-mail-smtp' ),
|
70 |
-
'<a href="https://app.sendgrid.com/settings/api_keys" target="_blank" rel="noopener noreferrer">' .
|
71 |
-
esc_html__( 'Create API Key', 'wp-mail-smtp' ) .
|
72 |
-
'</a>'
|
73 |
-
);
|
74 |
-
?>
|
75 |
-
<br/>
|
76 |
-
<?php
|
77 |
-
printf(
|
78 |
-
/* translators: %s - SendGrid access level. */
|
79 |
-
esc_html__( 'To send emails you will need only a %s access level for this API key.', 'wp-mail-smtp' ),
|
80 |
-
'<code>Mail Send</code>'
|
81 |
-
);
|
82 |
-
?>
|
83 |
-
</p>
|
84 |
-
</div>
|
85 |
-
</div>
|
86 |
-
|
87 |
-
<?php
|
88 |
-
}
|
89 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP\Providers\Sendgrid;
|
4 |
+
|
5 |
+
use WPMailSMTP\Providers\OptionAbstract;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class Option.
|
9 |
+
*
|
10 |
+
* @since 1.0.0
|
11 |
+
*/
|
12 |
+
class Options extends OptionAbstract {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Options constructor.
|
16 |
+
*
|
17 |
+
* @since 1.0.0
|
18 |
+
*/
|
19 |
+
public function __construct() {
|
20 |
+
|
21 |
+
parent::__construct(
|
22 |
+
array(
|
23 |
+
'logo_url' => wp_mail_smtp()->plugin_url . '/assets/images/sendgrid.png',
|
24 |
+
'slug' => 'sendgrid',
|
25 |
+
'title' => esc_html__( 'SendGrid', 'wp-mail-smtp' ),
|
26 |
+
'description' => sprintf(
|
27 |
+
wp_kses(
|
28 |
+
/* translators: %1$s - opening link tag; %2$s - closing link tag; %3$s - opening link tag; %4$s - closing link tag. */
|
29 |
+
__( '%1$sSendGrid%2$s is one of the leading transactional email services, sending over 35 billion emails every month. They provide users 100 free emails per month.<br><br>Read our %3$sSendGrid documentation%4$s to learn how to set up SendGrid and improve your email deliverability.', 'wp-mail-smtp' ),
|
30 |
+
array(
|
31 |
+
'br' => array(),
|
32 |
+
'a' => array(
|
33 |
+
'href' => array(),
|
34 |
+
'rel' => array(),
|
35 |
+
'target' => array(),
|
36 |
+
),
|
37 |
+
)
|
38 |
+
),
|
39 |
+
'<a href="https://sendgrid.com" target="_blank" rel="noopener noreferrer">',
|
40 |
+
'</a>',
|
41 |
+
'<a href="https://wpforms.com/fix-wordpress-email-notifications-with-sendgrid/" target="_blank" rel="noopener noreferrer">',
|
42 |
+
'</a>'
|
43 |
+
),
|
44 |
+
)
|
45 |
+
);
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* @inheritdoc
|
50 |
+
*/
|
51 |
+
public function display_options() {
|
52 |
+
?>
|
53 |
+
|
54 |
+
<!-- API Key -->
|
55 |
+
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-api_key" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
|
56 |
+
<div class="wp-mail-smtp-setting-label">
|
57 |
+
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"><?php esc_html_e( 'API Key', 'wp-mail-smtp' ); ?></label>
|
58 |
+
</div>
|
59 |
+
<div class="wp-mail-smtp-setting-field">
|
60 |
+
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][api_key]" type="text"
|
61 |
+
value="<?php echo esc_attr( $this->options->get( $this->get_slug(), 'api_key' ) ); ?>"
|
62 |
+
<?php echo $this->options->is_const_defined( $this->get_slug(), 'api_key' ) ? 'disabled' : ''; ?>
|
63 |
+
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key" spellcheck="false"
|
64 |
+
/>
|
65 |
+
<p class="desc">
|
66 |
+
<?php
|
67 |
+
printf(
|
68 |
+
/* translators: %s - API key link. */
|
69 |
+
esc_html__( 'Follow this link to get an API Key from SendGrid: %s.', 'wp-mail-smtp' ),
|
70 |
+
'<a href="https://app.sendgrid.com/settings/api_keys" target="_blank" rel="noopener noreferrer">' .
|
71 |
+
esc_html__( 'Create API Key', 'wp-mail-smtp' ) .
|
72 |
+
'</a>'
|
73 |
+
);
|
74 |
+
?>
|
75 |
+
<br/>
|
76 |
+
<?php
|
77 |
+
printf(
|
78 |
+
/* translators: %s - SendGrid access level. */
|
79 |
+
esc_html__( 'To send emails you will need only a %s access level for this API key.', 'wp-mail-smtp' ),
|
80 |
+
'<code>Mail Send</code>'
|
81 |
+
);
|
82 |
+
?>
|
83 |
+
</p>
|
84 |
+
</div>
|
85 |
+
</div>
|
86 |
+
|
87 |
+
<?php
|
88 |
+
}
|
89 |
+
}
|
src/Upgrade.php
ADDED
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Class Upgrade helps upgrade plugin options and similar tasks when the
|
7 |
+
* occasion arises.
|
8 |
+
*
|
9 |
+
* @since 1.1.0
|
10 |
+
*/
|
11 |
+
class Upgrade {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Upgrade constructor.
|
15 |
+
*
|
16 |
+
* @since 1.1.0
|
17 |
+
*/
|
18 |
+
public function __construct() {
|
19 |
+
|
20 |
+
$upgrades = $this->upgrades();
|
21 |
+
|
22 |
+
if ( empty( $upgrades ) ) {
|
23 |
+
return;
|
24 |
+
}
|
25 |
+
|
26 |
+
// Run any available upgrades.
|
27 |
+
foreach ( $upgrades as $upgrade ) {
|
28 |
+
$this->{$upgrade}();
|
29 |
+
}
|
30 |
+
|
31 |
+
// Update version post upgrade(s).
|
32 |
+
update_option( 'wp_mail_smtp_version', WPMS_PLUGIN_VER );
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Whether we need to perform an upgrade.
|
37 |
+
*
|
38 |
+
* @since 1.1.0
|
39 |
+
*
|
40 |
+
* @return array
|
41 |
+
*/
|
42 |
+
protected function upgrades() {
|
43 |
+
|
44 |
+
$version = get_option( 'wp_mail_smtp_version' );
|
45 |
+
$upgrades = array();
|
46 |
+
|
47 |
+
// Version 1.1.0 upgrade; prior to this the option was not available.
|
48 |
+
if ( empty( $version ) ) {
|
49 |
+
$upgrades[] = 'v110_upgrade';
|
50 |
+
}
|
51 |
+
|
52 |
+
return $upgrades;
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Upgrade routine for v1.1.0.
|
57 |
+
*
|
58 |
+
* Set SMTPAutoTLS to true.
|
59 |
+
*
|
60 |
+
* @since 1.1.0
|
61 |
+
*/
|
62 |
+
public function v110_upgrade() {
|
63 |
+
|
64 |
+
$values = Options::init()->get_all();
|
65 |
+
|
66 |
+
// Enable SMTPAutoTLS option.
|
67 |
+
$values['smtp']['autotls'] = true;
|
68 |
+
|
69 |
+
Options::init()->set( $values );
|
70 |
+
}
|
71 |
+
}
|
src/WP.php
CHANGED
@@ -1,140 +1,140 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
namespace WPMailSMTP;
|
4 |
-
|
5 |
-
/**
|
6 |
-
* Class WP provides WordPress shortcuts.
|
7 |
-
*
|
8 |
-
* @since 1.0.0
|
9 |
-
*/
|
10 |
-
class WP {
|
11 |
-
|
12 |
-
/**
|
13 |
-
* The "queue" of notices.
|
14 |
-
*
|
15 |
-
* @var array
|
16 |
-
*/
|
17 |
-
protected static $admin_notices = array();
|
18 |
-
/**
|
19 |
-
* @var string
|
20 |
-
*/
|
21 |
-
const ADMIN_NOTICE_SUCCESS = 'notice-success';
|
22 |
-
/**
|
23 |
-
* @var string
|
24 |
-
*/
|
25 |
-
const ADMIN_NOTICE_ERROR = 'notice-error';
|
26 |
-
/**
|
27 |
-
* @var string
|
28 |
-
*/
|
29 |
-
const ADMIN_NOTICE_INFO = 'notice-info';
|
30 |
-
/**
|
31 |
-
* @var string
|
32 |
-
*/
|
33 |
-
const ADMIN_NOTICE_WARNING = 'notice-warning';
|
34 |
-
|
35 |
-
/**
|
36 |
-
* True is WP is processing an AJAX call.
|
37 |
-
*
|
38 |
-
* @since 1.0.0
|
39 |
-
*
|
40 |
-
* @return bool
|
41 |
-
*/
|
42 |
-
public static function is_doing_ajax() {
|
43 |
-
|
44 |
-
if ( function_exists( 'wp_doing_ajax' ) ) {
|
45 |
-
return wp_doing_ajax();
|
46 |
-
}
|
47 |
-
|
48 |
-
return ( defined( 'DOING_AJAX' ) && DOING_AJAX );
|
49 |
-
}
|
50 |
-
|
51 |
-
/**
|
52 |
-
* True if I am in the Admin Panel, not doing AJAX.
|
53 |
-
*
|
54 |
-
* @since 1.0.0
|
55 |
-
*
|
56 |
-
* @return bool
|
57 |
-
*/
|
58 |
-
public static function in_wp_admin() {
|
59 |
-
return ( is_admin() && ! self::is_doing_ajax() );
|
60 |
-
}
|
61 |
-
|
62 |
-
/**
|
63 |
-
* Add a notice to the "queue of notices".
|
64 |
-
*
|
65 |
-
* @since 1.0.0
|
66 |
-
*
|
67 |
-
* @param string $message Message text (HTML is OK).
|
68 |
-
* @param string $class Display class (severity).
|
69 |
-
*/
|
70 |
-
public static function add_admin_notice( $message, $class = self::ADMIN_NOTICE_INFO ) {
|
71 |
-
|
72 |
-
self::$admin_notices[] = array(
|
73 |
-
'message' => $message,
|
74 |
-
'class' => $class,
|
75 |
-
);
|
76 |
-
}
|
77 |
-
|
78 |
-
/**
|
79 |
-
* Display all notices.
|
80 |
-
*
|
81 |
-
* @since 1.0.0
|
82 |
-
*/
|
83 |
-
public static function display_admin_notices() {
|
84 |
-
|
85 |
-
foreach ( (array) self::$admin_notices as $notice ) : ?>
|
86 |
-
|
87 |
-
<div id="message" class="<?php echo esc_attr( $notice['class'] ); ?> notice is-dismissible">
|
88 |
-
<p>
|
89 |
-
<?php echo $notice['message']; ?>
|
90 |
-
</p>
|
91 |
-
</div>
|
92 |
-
|
93 |
-
<?php
|
94 |
-
endforeach;
|
95 |
-
}
|
96 |
-
|
97 |
-
/**
|
98 |
-
* Check whether WP_DEBUG is active.
|
99 |
-
*
|
100 |
-
* @since 1.0.0
|
101 |
-
*
|
102 |
-
* @return bool
|
103 |
-
*/
|
104 |
-
public static function is_debug() {
|
105 |
-
return defined( 'WP_DEBUG' ) && WP_DEBUG;
|
106 |
-
}
|
107 |
-
|
108 |
-
/**
|
109 |
-
* Shortcut to global $wpdb.
|
110 |
-
*
|
111 |
-
* @since 1.0.0
|
112 |
-
*
|
113 |
-
* @return \wpdb
|
114 |
-
*/
|
115 |
-
public static function wpdb() {
|
116 |
-
|
117 |
-
global $wpdb;
|
118 |
-
|
119 |
-
return $wpdb;
|
120 |
-
}
|
121 |
-
|
122 |
-
/**
|
123 |
-
* Get the postfix for assets files - ".min" or empty.
|
124 |
-
* ".min" if in production mode.
|
125 |
-
*
|
126 |
-
* @since 1.0.0
|
127 |
-
*
|
128 |
-
* @return string
|
129 |
-
*/
|
130 |
-
public static function asset_min() {
|
131 |
-
|
132 |
-
$min = '.min';
|
133 |
-
|
134 |
-
if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
|
135 |
-
$min = '';
|
136 |
-
}
|
137 |
-
|
138 |
-
return $min;
|
139 |
-
}
|
140 |
-
}
|
1 |
+
<?php
|
2 |
+
|
3 |
+
namespace WPMailSMTP;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Class WP provides WordPress shortcuts.
|
7 |
+
*
|
8 |
+
* @since 1.0.0
|
9 |
+
*/
|
10 |
+
class WP {
|
11 |
+
|
12 |
+
/**
|
13 |
+
* The "queue" of notices.
|
14 |
+
*
|
15 |
+
* @var array
|
16 |
+
*/
|
17 |
+
protected static $admin_notices = array();
|
18 |
+
/**
|
19 |
+
* @var string
|
20 |
+
*/
|
21 |
+
const ADMIN_NOTICE_SUCCESS = 'notice-success';
|
22 |
+
/**
|
23 |
+
* @var string
|
24 |
+
*/
|
25 |
+
const ADMIN_NOTICE_ERROR = 'notice-error';
|
26 |
+
/**
|
27 |
+
* @var string
|
28 |
+
*/
|
29 |
+
const ADMIN_NOTICE_INFO = 'notice-info';
|
30 |
+
/**
|
31 |
+
* @var string
|
32 |
+
*/
|
33 |
+
const ADMIN_NOTICE_WARNING = 'notice-warning';
|
34 |
+
|
35 |
+
/**
|
36 |
+
* True is WP is processing an AJAX call.
|
37 |
+
*
|
38 |
+
* @since 1.0.0
|
39 |
+
*
|
40 |
+
* @return bool
|
41 |
+
*/
|
42 |
+
public static function is_doing_ajax() {
|
43 |
+
|
44 |
+
if ( function_exists( 'wp_doing_ajax' ) ) {
|
45 |
+
return wp_doing_ajax();
|
46 |
+
}
|
47 |
+
|
48 |
+
return ( defined( 'DOING_AJAX' ) && DOING_AJAX );
|
49 |
+
}
|
50 |
+
|
51 |
+
/**
|
52 |
+
* True if I am in the Admin Panel, not doing AJAX.
|
53 |
+
*
|
54 |
+
* @since 1.0.0
|
55 |
+
*
|
56 |
+
* @return bool
|
57 |
+
*/
|
58 |
+
public static function in_wp_admin() {
|
59 |
+
return ( is_admin() && ! self::is_doing_ajax() );
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Add a notice to the "queue of notices".
|
64 |
+
*
|
65 |
+
* @since 1.0.0
|
66 |
+
*
|
67 |
+
* @param string $message Message text (HTML is OK).
|
68 |
+
* @param string $class Display class (severity).
|
69 |
+
*/
|
70 |
+
public static function add_admin_notice( $message, $class = self::ADMIN_NOTICE_INFO ) {
|
71 |
+
|
72 |
+
self::$admin_notices[] = array(
|
73 |
+
'message' => $message,
|
74 |
+
'class' => $class,
|
75 |
+
);
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Display all notices.
|
80 |
+
*
|
81 |
+
* @since 1.0.0
|
82 |
+
*/
|
83 |
+
public static function display_admin_notices() {
|
84 |
+
|
85 |
+
foreach ( (array) self::$admin_notices as $notice ) : ?>
|
86 |
+
|
87 |
+
<div id="message" class="<?php echo esc_attr( $notice['class'] ); ?> notice is-dismissible">
|
88 |
+
<p>
|
89 |
+
<?php echo $notice['message']; ?>
|
90 |
+
</p>
|
91 |
+
</div>
|
92 |
+
|
93 |
+
<?php
|
94 |
+
endforeach;
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Check whether WP_DEBUG is active.
|
99 |
+
*
|
100 |
+
* @since 1.0.0
|
101 |
+
*
|
102 |
+
* @return bool
|
103 |
+
*/
|
104 |
+
public static function is_debug() {
|
105 |
+
return defined( 'WP_DEBUG' ) && WP_DEBUG;
|
106 |
+
}
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Shortcut to global $wpdb.
|
110 |
+
*
|
111 |
+
* @since 1.0.0
|
112 |
+
*
|
113 |
+
* @return \wpdb
|
114 |
+
*/
|
115 |
+
public static function wpdb() {
|
116 |
+
|
117 |
+
global $wpdb;
|
118 |
+
|
119 |
+
return $wpdb;
|
120 |
+
}
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Get the postfix for assets files - ".min" or empty.
|
124 |
+
* ".min" if in production mode.
|
125 |
+
*
|
126 |
+
* @since 1.0.0
|
127 |
+
*
|
128 |
+
* @return string
|
129 |
+
*/
|
130 |
+
public static function asset_min() {
|
131 |
+
|
132 |
+
$min = '.min';
|
133 |
+
|
134 |
+
if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
|
135 |
+
$min = '';
|
136 |
+
}
|
137 |
+
|
138 |
+
return $min;
|
139 |
+
}
|
140 |
+
}
|
vendor/autoload.php
CHANGED
@@ -2,6 +2,6 @@
|
|
2 |
|
3 |
// autoload.php @generated by Composer
|
4 |
|
5 |
-
require_once __DIR__ . '/composer
|
6 |
|
7 |
-
return
|
2 |
|
3 |
// autoload.php @generated by Composer
|
4 |
|
5 |
+
require_once __DIR__ . '/composer/autoload_real.php';
|
6 |
|
7 |
+
return ComposerAutoloaderInitbd625bfb904527ebcdc364a59295e538::getLoader();
|
vendor/composer/ClassLoader.php
CHANGED
@@ -53,8 +53,9 @@ class ClassLoader
|
|
53 |
|
54 |
private $useIncludePath = false;
|
55 |
private $classMap = array();
|
56 |
-
|
57 |
private $classMapAuthoritative = false;
|
|
|
|
|
58 |
|
59 |
public function getPrefixes()
|
60 |
{
|
@@ -271,6 +272,26 @@ class ClassLoader
|
|
271 |
return $this->classMapAuthoritative;
|
272 |
}
|
273 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
274 |
/**
|
275 |
* Registers this instance as an autoloader.
|
276 |
*
|
@@ -313,29 +334,34 @@ class ClassLoader
|
|
313 |
*/
|
314 |
public function findFile($class)
|
315 |
{
|
316 |
-
// work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
|
317 |
-
if ('\\' == $class[0]) {
|
318 |
-
$class = substr($class, 1);
|
319 |
-
}
|
320 |
-
|
321 |
// class map lookup
|
322 |
if (isset($this->classMap[$class])) {
|
323 |
return $this->classMap[$class];
|
324 |
}
|
325 |
-
if ($this->classMapAuthoritative) {
|
326 |
return false;
|
327 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
328 |
|
329 |
$file = $this->findFileWithExtension($class, '.php');
|
330 |
|
331 |
// Search for Hack files if we are running on HHVM
|
332 |
-
if (
|
333 |
$file = $this->findFileWithExtension($class, '.hh');
|
334 |
}
|
335 |
|
336 |
-
if (
|
|
|
|
|
|
|
|
|
337 |
// Remember that this class does not exist.
|
338 |
-
|
339 |
}
|
340 |
|
341 |
return $file;
|
@@ -348,9 +374,13 @@ class ClassLoader
|
|
348 |
|
349 |
$first = $class[0];
|
350 |
if (isset($this->prefixLengthsPsr4[$first])) {
|
351 |
-
|
352 |
-
|
353 |
-
|
|
|
|
|
|
|
|
|
354 |
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
|
355 |
return $file;
|
356 |
}
|
@@ -399,6 +429,8 @@ class ClassLoader
|
|
399 |
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
400 |
return $file;
|
401 |
}
|
|
|
|
|
402 |
}
|
403 |
}
|
404 |
|
53 |
|
54 |
private $useIncludePath = false;
|
55 |
private $classMap = array();
|
|
|
56 |
private $classMapAuthoritative = false;
|
57 |
+
private $missingClasses = array();
|
58 |
+
private $apcuPrefix;
|
59 |
|
60 |
public function getPrefixes()
|
61 |
{
|
272 |
return $this->classMapAuthoritative;
|
273 |
}
|
274 |
|
275 |
+
/**
|
276 |
+
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
277 |
+
*
|
278 |
+
* @param string|null $apcuPrefix
|
279 |
+
*/
|
280 |
+
public function setApcuPrefix($apcuPrefix)
|
281 |
+
{
|
282 |
+
$this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
|
283 |
+
}
|
284 |
+
|
285 |
+
/**
|
286 |
+
* The APCu prefix in use, or null if APCu caching is not enabled.
|
287 |
+
*
|
288 |
+
* @return string|null
|
289 |
+
*/
|
290 |
+
public function getApcuPrefix()
|
291 |
+
{
|
292 |
+
return $this->apcuPrefix;
|
293 |
+
}
|
294 |
+
|
295 |
/**
|
296 |
* Registers this instance as an autoloader.
|
297 |
*
|
334 |
*/
|
335 |
public function findFile($class)
|
336 |
{
|
|
|
|
|
|
|
|
|
|
|
337 |
// class map lookup
|
338 |
if (isset($this->classMap[$class])) {
|
339 |
return $this->classMap[$class];
|
340 |
}
|
341 |
+
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
342 |
return false;
|
343 |
}
|
344 |
+
if (null !== $this->apcuPrefix) {
|
345 |
+
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
346 |
+
if ($hit) {
|
347 |
+
return $file;
|
348 |
+
}
|
349 |
+
}
|
350 |
|
351 |
$file = $this->findFileWithExtension($class, '.php');
|
352 |
|
353 |
// Search for Hack files if we are running on HHVM
|
354 |
+
if (false === $file && defined('HHVM_VERSION')) {
|
355 |
$file = $this->findFileWithExtension($class, '.hh');
|
356 |
}
|
357 |
|
358 |
+
if (null !== $this->apcuPrefix) {
|
359 |
+
apcu_add($this->apcuPrefix.$class, $file);
|
360 |
+
}
|
361 |
+
|
362 |
+
if (false === $file) {
|
363 |
// Remember that this class does not exist.
|
364 |
+
$this->missingClasses[$class] = true;
|
365 |
}
|
366 |
|
367 |
return $file;
|
374 |
|
375 |
$first = $class[0];
|
376 |
if (isset($this->prefixLengthsPsr4[$first])) {
|
377 |
+
$subPath = $class;
|
378 |
+
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
379 |
+
$subPath = substr($subPath, 0, $lastPos);
|
380 |
+
$search = $subPath.'\\';
|
381 |
+
if (isset($this->prefixDirsPsr4[$search])) {
|
382 |
+
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
383 |
+
$length = $this->prefixLengthsPsr4[$first][$search];
|
384 |
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
|
385 |
return $file;
|
386 |
}
|
429 |
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
430 |
return $file;
|
431 |
}
|
432 |
+
|
433 |
+
return false;
|
434 |
}
|
435 |
}
|
436 |
|
vendor/composer/LICENSE
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
|
2 |
-
Copyright (c)
|
3 |
|
4 |
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5 |
of this software and associated documentation files (the "Software"), to deal
|
1 |
|
2 |
+
Copyright (c) Nils Adermann, Jordi Boggiano
|
3 |
|
4 |
Permission is hereby granted, free of charge, to any person obtaining a copy
|
5 |
of this software and associated documentation files (the "Software"), to deal
|
vendor/composer/autoload_classmap.php
CHANGED
@@ -6,6 +6,234 @@ $vendorDir = dirname(dirname(__FILE__));
|
|
6 |
$baseDir = dirname($vendorDir);
|
7 |
|
8 |
return array(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
'Google_Service_Exception' => $vendorDir . '/google/apiclient/src/Google/Service/Exception.php',
|
10 |
'Google_Service_Resource' => $vendorDir . '/google/apiclient/src/Google/Service/Resource.php',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
);
|
6 |
$baseDir = dirname($vendorDir);
|
7 |
|
8 |
return array(
|
9 |
+
'Google\\Auth\\ApplicationDefaultCredentials' => $vendorDir . '/google/auth/src/ApplicationDefaultCredentials.php',
|
10 |
+
'Google\\Auth\\CacheTrait' => $vendorDir . '/google/auth/src/CacheTrait.php',
|
11 |
+
'Google\\Auth\\Cache\\InvalidArgumentException' => $vendorDir . '/google/auth/src/Cache/InvalidArgumentException.php',
|
12 |
+
'Google\\Auth\\Cache\\Item' => $vendorDir . '/google/auth/src/Cache/Item.php',
|
13 |
+
'Google\\Auth\\Cache\\MemoryCacheItemPool' => $vendorDir . '/google/auth/src/Cache/MemoryCacheItemPool.php',
|
14 |
+
'Google\\Auth\\CredentialsLoader' => $vendorDir . '/google/auth/src/CredentialsLoader.php',
|
15 |
+
'Google\\Auth\\Credentials\\AppIdentityCredentials' => $vendorDir . '/google/auth/src/Credentials/AppIdentityCredentials.php',
|
16 |
+
'Google\\Auth\\Credentials\\GCECredentials' => $vendorDir . '/google/auth/src/Credentials/GCECredentials.php',
|
17 |
+
'Google\\Auth\\Credentials\\IAMCredentials' => $vendorDir . '/google/auth/src/Credentials/IAMCredentials.php',
|
18 |
+
'Google\\Auth\\Credentials\\ServiceAccountCredentials' => $vendorDir . '/google/auth/src/Credentials/ServiceAccountCredentials.php',
|
19 |
+
'Google\\Auth\\Credentials\\ServiceAccountJwtAccessCredentials' => $vendorDir . '/google/auth/src/Credentials/ServiceAccountJwtAccessCredentials.php',
|
20 |
+
'Google\\Auth\\Credentials\\UserRefreshCredentials' => $vendorDir . '/google/auth/src/Credentials/UserRefreshCredentials.php',
|
21 |
+
'Google\\Auth\\FetchAuthTokenCache' => $vendorDir . '/google/auth/src/FetchAuthTokenCache.php',
|
22 |
+
'Google\\Auth\\FetchAuthTokenInterface' => $vendorDir . '/google/auth/src/FetchAuthTokenInterface.php',
|
23 |
+
'Google\\Auth\\HttpHandler\\Guzzle5HttpHandler' => $vendorDir . '/google/auth/src/HttpHandler/Guzzle5HttpHandler.php',
|
24 |
+
'Google\\Auth\\HttpHandler\\Guzzle6HttpHandler' => $vendorDir . '/google/auth/src/HttpHandler/Guzzle6HttpHandler.php',
|
25 |
+
'Google\\Auth\\HttpHandler\\HttpHandlerFactory' => $vendorDir . '/google/auth/src/HttpHandler/HttpHandlerFactory.php',
|
26 |
+
'Google\\Auth\\Middleware\\AuthTokenMiddleware' => $vendorDir . '/google/auth/src/Middleware/AuthTokenMiddleware.php',
|
27 |
+
'Google\\Auth\\Middleware\\ScopedAccessTokenMiddleware' => $vendorDir . '/google/auth/src/Middleware/ScopedAccessTokenMiddleware.php',
|
28 |
+
'Google\\Auth\\Middleware\\SimpleMiddleware' => $vendorDir . '/google/auth/src/Middleware/SimpleMiddleware.php',
|
29 |
+
'Google\\Auth\\OAuth2' => $vendorDir . '/google/auth/src/OAuth2.php',
|
30 |
+
'Google\\Auth\\Subscriber\\AuthTokenSubscriber' => $vendorDir . '/google/auth/src/Subscriber/AuthTokenSubscriber.php',
|
31 |
+
'Google\\Auth\\Subscriber\\ScopedAccessTokenSubscriber' => $vendorDir . '/google/auth/src/Subscriber/ScopedAccessTokenSubscriber.php',
|
32 |
+
'Google\\Auth\\Subscriber\\SimpleSubscriber' => $vendorDir . '/google/auth/src/Subscriber/SimpleSubscriber.php',
|
33 |
+
'Google_AccessToken_Revoke' => $vendorDir . '/google/apiclient/src/Google/AccessToken/Revoke.php',
|
34 |
+
'Google_AccessToken_Verify' => $vendorDir . '/google/apiclient/src/Google/AccessToken/Verify.php',
|
35 |
+
'Google_AuthHandler_AuthHandlerFactory' => $vendorDir . '/google/apiclient/src/Google/AuthHandler/AuthHandlerFactory.php',
|
36 |
+
'Google_AuthHandler_Guzzle5AuthHandler' => $vendorDir . '/google/apiclient/src/Google/AuthHandler/Guzzle5AuthHandler.php',
|
37 |
+
'Google_AuthHandler_Guzzle6AuthHandler' => $vendorDir . '/google/apiclient/src/Google/AuthHandler/Guzzle6AuthHandler.php',
|
38 |
+
'Google_Client' => $vendorDir . '/google/apiclient/src/Google/Client.php',
|
39 |
+
'Google_Collection' => $vendorDir . '/google/apiclient/src/Google/Collection.php',
|
40 |
+
'Google_Exception' => $vendorDir . '/google/apiclient/src/Google/Exception.php',
|
41 |
+
'Google_Http_Batch' => $vendorDir . '/google/apiclient/src/Google/Http/Batch.php',
|
42 |
+
'Google_Http_MediaFileUpload' => $vendorDir . '/google/apiclient/src/Google/Http/MediaFileUpload.php',
|
43 |
+
'Google_Http_REST' => $vendorDir . '/google/apiclient/src/Google/Http/REST.php',
|
44 |
+
'Google_Model' => $vendorDir . '/google/apiclient/src/Google/Model.php',
|
45 |
+
'Google_Service' => $vendorDir . '/google/apiclient/src/Google/Service.php',
|
46 |
'Google_Service_Exception' => $vendorDir . '/google/apiclient/src/Google/Service/Exception.php',
|
47 |
'Google_Service_Resource' => $vendorDir . '/google/apiclient/src/Google/Service/Resource.php',
|
48 |
+
'Google_Task_Exception' => $vendorDir . '/google/apiclient/src/Google/Task/Exception.php',
|
49 |
+
'Google_Task_Retryable' => $vendorDir . '/google/apiclient/src/Google/Task/Retryable.php',
|
50 |
+
'Google_Task_Runner' => $vendorDir . '/google/apiclient/src/Google/Task/Runner.php',
|
51 |
+
'Google_Utils_UriTemplate' => $vendorDir . '/google/apiclient/src/Google/Utils/UriTemplate.php',
|
52 |
+
'GuzzleHttp\\Client' => $vendorDir . '/guzzlehttp/guzzle/src/Client.php',
|
53 |
+
'GuzzleHttp\\ClientInterface' => $vendorDir . '/guzzlehttp/guzzle/src/ClientInterface.php',
|
54 |
+
'GuzzleHttp\\Cookie\\CookieJar' => $vendorDir . '/guzzlehttp/guzzle/src/Cookie/CookieJar.php',
|
55 |
+
'GuzzleHttp\\Cookie\\CookieJarInterface' => $vendorDir . '/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php',
|
56 |
+
'GuzzleHttp\\Cookie\\FileCookieJar' => $vendorDir . '/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php',
|
57 |
+
'GuzzleHttp\\Cookie\\SessionCookieJar' => $vendorDir . '/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php',
|
58 |
+
'GuzzleHttp\\Cookie\\SetCookie' => $vendorDir . '/guzzlehttp/guzzle/src/Cookie/SetCookie.php',
|
59 |
+
'GuzzleHttp\\Exception\\BadResponseException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/BadResponseException.php',
|
60 |
+
'GuzzleHttp\\Exception\\ClientException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/ClientException.php',
|
61 |
+
'GuzzleHttp\\Exception\\ConnectException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/ConnectException.php',
|
62 |
+
'GuzzleHttp\\Exception\\GuzzleException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/GuzzleException.php',
|
63 |
+
'GuzzleHttp\\Exception\\RequestException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/RequestException.php',
|
64 |
+
'GuzzleHttp\\Exception\\SeekException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/SeekException.php',
|
65 |
+
'GuzzleHttp\\Exception\\ServerException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/ServerException.php',
|
66 |
+
'GuzzleHttp\\Exception\\TooManyRedirectsException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php',
|
67 |
+
'GuzzleHttp\\Exception\\TransferException' => $vendorDir . '/guzzlehttp/guzzle/src/Exception/TransferException.php',
|
68 |
+
'GuzzleHttp\\HandlerStack' => $vendorDir . '/guzzlehttp/guzzle/src/HandlerStack.php',
|
69 |
+
'GuzzleHttp\\Handler\\CurlFactory' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/CurlFactory.php',
|
70 |
+
'GuzzleHttp\\Handler\\CurlFactoryInterface' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php',
|
71 |
+
'GuzzleHttp\\Handler\\CurlHandler' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/CurlHandler.php',
|
72 |
+
'GuzzleHttp\\Handler\\CurlMultiHandler' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php',
|
73 |
+
'GuzzleHttp\\Handler\\EasyHandle' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/EasyHandle.php',
|
74 |
+
'GuzzleHttp\\Handler\\MockHandler' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/MockHandler.php',
|
75 |
+
'GuzzleHttp\\Handler\\Proxy' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/Proxy.php',
|
76 |
+
'GuzzleHttp\\Handler\\StreamHandler' => $vendorDir . '/guzzlehttp/guzzle/src/Handler/StreamHandler.php',
|
77 |
+
'GuzzleHttp\\MessageFormatter' => $vendorDir . '/guzzlehttp/guzzle/src/MessageFormatter.php',
|
78 |
+
'GuzzleHttp\\Middleware' => $vendorDir . '/guzzlehttp/guzzle/src/Middleware.php',
|
79 |
+
'GuzzleHttp\\Pool' => $vendorDir . '/guzzlehttp/guzzle/src/Pool.php',
|
80 |
+
'GuzzleHttp\\PrepareBodyMiddleware' => $vendorDir . '/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php',
|
81 |
+
'GuzzleHttp\\Promise\\AggregateException' => $vendorDir . '/guzzlehttp/promises/src/AggregateException.php',
|
82 |
+
'GuzzleHttp\\Promise\\CancellationException' => $vendorDir . '/guzzlehttp/promises/src/CancellationException.php',
|
83 |
+
'GuzzleHttp\\Promise\\Coroutine' => $vendorDir . '/guzzlehttp/promises/src/Coroutine.php',
|
84 |
+
'GuzzleHttp\\Promise\\EachPromise' => $vendorDir . '/guzzlehttp/promises/src/EachPromise.php',
|
85 |
+
'GuzzleHttp\\Promise\\FulfilledPromise' => $vendorDir . '/guzzlehttp/promises/src/FulfilledPromise.php',
|
86 |
+
'GuzzleHttp\\Promise\\Promise' => $vendorDir . '/guzzlehttp/promises/src/Promise.php',
|
87 |
+
'GuzzleHttp\\Promise\\PromiseInterface' => $vendorDir . '/guzzlehttp/promises/src/PromiseInterface.php',
|
88 |
+
'GuzzleHttp\\Promise\\PromisorInterface' => $vendorDir . '/guzzlehttp/promises/src/PromisorInterface.php',
|
89 |
+
'GuzzleHttp\\Promise\\RejectedPromise' => $vendorDir . '/guzzlehttp/promises/src/RejectedPromise.php',
|
90 |
+
'GuzzleHttp\\Promise\\RejectionException' => $vendorDir . '/guzzlehttp/promises/src/RejectionException.php',
|
91 |
+
'GuzzleHttp\\Promise\\TaskQueue' => $vendorDir . '/guzzlehttp/promises/src/TaskQueue.php',
|
92 |
+
'GuzzleHttp\\Promise\\TaskQueueInterface' => $vendorDir . '/guzzlehttp/promises/src/TaskQueueInterface.php',
|
93 |
+
'GuzzleHttp\\Psr7\\AppendStream' => $vendorDir . '/guzzlehttp/psr7/src/AppendStream.php',
|
94 |
+
'GuzzleHttp\\Psr7\\BufferStream' => $vendorDir . '/guzzlehttp/psr7/src/BufferStream.php',
|
95 |
+
'GuzzleHttp\\Psr7\\CachingStream' => $vendorDir . '/guzzlehttp/psr7/src/CachingStream.php',
|
96 |
+
'GuzzleHttp\\Psr7\\DroppingStream' => $vendorDir . '/guzzlehttp/psr7/src/DroppingStream.php',
|
97 |
+
'GuzzleHttp\\Psr7\\FnStream' => $vendorDir . '/guzzlehttp/psr7/src/FnStream.php',
|
98 |
+
'GuzzleHttp\\Psr7\\InflateStream' => $vendorDir . '/guzzlehttp/psr7/src/InflateStream.php',
|
99 |
+
'GuzzleHttp\\Psr7\\LazyOpenStream' => $vendorDir . '/guzzlehttp/psr7/src/LazyOpenStream.php',
|
100 |
+
'GuzzleHttp\\Psr7\\LimitStream' => $vendorDir . '/guzzlehttp/psr7/src/LimitStream.php',
|
101 |
+
'GuzzleHttp\\Psr7\\MessageTrait' => $vendorDir . '/guzzlehttp/psr7/src/MessageTrait.php',
|
102 |
+
'GuzzleHttp\\Psr7\\MultipartStream' => $vendorDir . '/guzzlehttp/psr7/src/MultipartStream.php',
|
103 |
+
'GuzzleHttp\\Psr7\\NoSeekStream' => $vendorDir . '/guzzlehttp/psr7/src/NoSeekStream.php',
|
104 |
+
'GuzzleHttp\\Psr7\\PumpStream' => $vendorDir . '/guzzlehttp/psr7/src/PumpStream.php',
|
105 |
+
'GuzzleHttp\\Psr7\\Request' => $vendorDir . '/guzzlehttp/psr7/src/Request.php',
|
106 |
+
'GuzzleHttp\\Psr7\\Response' => $vendorDir . '/guzzlehttp/psr7/src/Response.php',
|
107 |
+
'GuzzleHttp\\Psr7\\ServerRequest' => $vendorDir . '/guzzlehttp/psr7/src/ServerRequest.php',
|
108 |
+
'GuzzleHttp\\Psr7\\Stream' => $vendorDir . '/guzzlehttp/psr7/src/Stream.php',
|
109 |
+
'GuzzleHttp\\Psr7\\StreamDecoratorTrait' => $vendorDir . '/guzzlehttp/psr7/src/StreamDecoratorTrait.php',
|
110 |
+
'GuzzleHttp\\Psr7\\StreamWrapper' => $vendorDir . '/guzzlehttp/psr7/src/StreamWrapper.php',
|
111 |
+
'GuzzleHttp\\Psr7\\UploadedFile' => $vendorDir . '/guzzlehttp/psr7/src/UploadedFile.php',
|
112 |
+
'GuzzleHttp\\Psr7\\Uri' => $vendorDir . '/guzzlehttp/psr7/src/Uri.php',
|
113 |
+
'GuzzleHttp\\Psr7\\UriNormalizer' => $vendorDir . '/guzzlehttp/psr7/src/UriNormalizer.php',
|
114 |
+
'GuzzleHttp\\Psr7\\UriResolver' => $vendorDir . '/guzzlehttp/psr7/src/UriResolver.php',
|
115 |
+
'GuzzleHttp\\RedirectMiddleware' => $vendorDir . '/guzzlehttp/guzzle/src/RedirectMiddleware.php',
|
116 |
+
'GuzzleHttp\\RequestOptions' => $vendorDir . '/guzzlehttp/guzzle/src/RequestOptions.php',
|
117 |
+
'GuzzleHttp\\RetryMiddleware' => $vendorDir . '/guzzlehttp/guzzle/src/RetryMiddleware.php',
|
118 |
+
'GuzzleHttp\\TransferStats' => $vendorDir . '/guzzlehttp/guzzle/src/TransferStats.php',
|
119 |
+
'GuzzleHttp\\UriTemplate' => $vendorDir . '/guzzlehttp/guzzle/src/UriTemplate.php',
|
120 |
+
'Monolog\\ErrorHandler' => $vendorDir . '/monolog/monolog/src/Monolog/ErrorHandler.php',
|
121 |
+
'Monolog\\Formatter\\ChromePHPFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php',
|
122 |
+
'Monolog\\Formatter\\ElasticaFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php',
|
123 |
+
'Monolog\\Formatter\\FlowdockFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php',
|
124 |
+
'Monolog\\Formatter\\FluentdFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php',
|
125 |
+
'Monolog\\Formatter\\FormatterInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php',
|
126 |
+
'Monolog\\Formatter\\GelfMessageFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php',
|
127 |
+
'Monolog\\Formatter\\HtmlFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php',
|
128 |
+
'Monolog\\Formatter\\JsonFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php',
|
129 |
+
'Monolog\\Formatter\\LineFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/LineFormatter.php',
|
130 |
+
'Monolog\\Formatter\\LogglyFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php',
|
131 |
+
'Monolog\\Formatter\\LogstashFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php',
|
132 |
+
'Monolog\\Formatter\\MongoDBFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php',
|
133 |
+
'Monolog\\Formatter\\NormalizerFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php',
|
134 |
+
'Monolog\\Formatter\\ScalarFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php',
|
135 |
+
'Monolog\\Formatter\\WildfireFormatter' => $vendorDir . '/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php',
|
136 |
+
'Monolog\\Handler\\AbstractHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AbstractHandler.php',
|
137 |
+
'Monolog\\Handler\\AbstractProcessingHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php',
|
138 |
+
'Monolog\\Handler\\AbstractSyslogHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php',
|
139 |
+
'Monolog\\Handler\\AmqpHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/AmqpHandler.php',
|
140 |
+
'Monolog\\Handler\\BrowserConsoleHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php',
|
141 |
+
'Monolog\\Handler\\BufferHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/BufferHandler.php',
|
142 |
+
'Monolog\\Handler\\ChromePHPHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php',
|
143 |
+
'Monolog\\Handler\\CouchDBHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php',
|
144 |
+
'Monolog\\Handler\\CubeHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/CubeHandler.php',
|
145 |
+
'Monolog\\Handler\\Curl\\Util' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/Curl/Util.php',
|
146 |
+
'Monolog\\Handler\\DeduplicationHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php',
|
147 |
+
'Monolog\\Handler\\DoctrineCouchDBHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php',
|
148 |
+
'Monolog\\Handler\\DynamoDbHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php',
|
149 |
+
'Monolog\\Handler\\ElasticSearchHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ElasticSearchHandler.php',
|
150 |
+
'Monolog\\Handler\\ErrorLogHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php',
|
151 |
+
'Monolog\\Handler\\FilterHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FilterHandler.php',
|
152 |
+
'Monolog\\Handler\\FingersCrossedHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php',
|
153 |
+
'Monolog\\Handler\\FingersCrossed\\ActivationStrategyInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php',
|
154 |
+
'Monolog\\Handler\\FingersCrossed\\ChannelLevelActivationStrategy' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php',
|
155 |
+
'Monolog\\Handler\\FingersCrossed\\ErrorLevelActivationStrategy' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php',
|
156 |
+
'Monolog\\Handler\\FirePHPHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php',
|
157 |
+
'Monolog\\Handler\\FleepHookHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php',
|
158 |
+
'Monolog\\Handler\\FlowdockHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php',
|
159 |
+
'Monolog\\Handler\\GelfHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/GelfHandler.php',
|
160 |
+
'Monolog\\Handler\\GroupHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/GroupHandler.php',
|
161 |
+
'Monolog\\Handler\\HandlerInterface' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/HandlerInterface.php',
|
162 |
+
'Monolog\\Handler\\HandlerWrapper' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php',
|
163 |
+
'Monolog\\Handler\\HipChatHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/HipChatHandler.php',
|
164 |
+
'Monolog\\Handler\\IFTTTHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php',
|
165 |
+
'Monolog\\Handler\\LogEntriesHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php',
|
166 |
+
'Monolog\\Handler\\LogglyHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/LogglyHandler.php',
|
167 |
+
'Monolog\\Handler\\MailHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MailHandler.php',
|
168 |
+
'Monolog\\Handler\\MandrillHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MandrillHandler.php',
|
169 |
+
'Monolog\\Handler\\MissingExtensionException' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php',
|
170 |
+
'Monolog\\Handler\\MongoDBHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php',
|
171 |
+
'Monolog\\Handler\\NativeMailerHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php',
|
172 |
+
'Monolog\\Handler\\NewRelicHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php',
|
173 |
+
'Monolog\\Handler\\NullHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/NullHandler.php',
|
174 |
+
'Monolog\\Handler\\PHPConsoleHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php',
|
175 |
+
'Monolog\\Handler\\PsrHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/PsrHandler.php',
|
176 |
+
'Monolog\\Handler\\PushoverHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/PushoverHandler.php',
|
177 |
+
'Monolog\\Handler\\RavenHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RavenHandler.php',
|
178 |
+
'Monolog\\Handler\\RedisHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RedisHandler.php',
|
179 |
+
'Monolog\\Handler\\RollbarHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RollbarHandler.php',
|
180 |
+
'Monolog\\Handler\\RotatingFileHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php',
|
181 |
+
'Monolog\\Handler\\SamplingHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SamplingHandler.php',
|
182 |
+
'Monolog\\Handler\\SlackHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SlackHandler.php',
|
183 |
+
'Monolog\\Handler\\SlackWebhookHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php',
|
184 |
+
'Monolog\\Handler\\Slack\\SlackRecord' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php',
|
185 |
+
'Monolog\\Handler\\SlackbotHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SlackbotHandler.php',
|
186 |
+
'Monolog\\Handler\\SocketHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SocketHandler.php',
|
187 |
+
'Monolog\\Handler\\StreamHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/StreamHandler.php',
|
188 |
+
'Monolog\\Handler\\SwiftMailerHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php',
|
189 |
+
'Monolog\\Handler\\SyslogHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SyslogHandler.php',
|
190 |
+
'Monolog\\Handler\\SyslogUdpHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php',
|
191 |
+
'Monolog\\Handler\\SyslogUdp\\UdpSocket' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php',
|
192 |
+
'Monolog\\Handler\\WhatFailureGroupHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php',
|
193 |
+
'Monolog\\Handler\\ZendMonitorHandler' => $vendorDir . '/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php',
|
194 |
+
'Monolog\\Logger' => $vendorDir . '/monolog/monolog/src/Monolog/Logger.php',
|
195 |
+
'Monolog\\Processor\\GitProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/GitProcessor.php',
|
196 |
+
'Monolog\\Processor\\IntrospectionProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php',
|
197 |
+
'Monolog\\Processor\\MemoryPeakUsageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php',
|
198 |
+
'Monolog\\Processor\\MemoryProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php',
|
199 |
+
'Monolog\\Processor\\MemoryUsageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php',
|
200 |
+
'Monolog\\Processor\\MercurialProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php',
|
201 |
+
'Monolog\\Processor\\ProcessIdProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php',
|
202 |
+
'Monolog\\Processor\\PsrLogMessageProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php',
|
203 |
+
'Monolog\\Processor\\TagProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/TagProcessor.php',
|
204 |
+
'Monolog\\Processor\\UidProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/UidProcessor.php',
|
205 |
+
'Monolog\\Processor\\WebProcessor' => $vendorDir . '/monolog/monolog/src/Monolog/Processor/WebProcessor.php',
|
206 |
+
'Monolog\\Registry' => $vendorDir . '/monolog/monolog/src/Monolog/Registry.php',
|
207 |
+
'Psr\\Cache\\CacheException' => $vendorDir . '/psr/cache/src/CacheException.php',
|
208 |
+
'Psr\\Cache\\CacheItemInterface' => $vendorDir . '/psr/cache/src/CacheItemInterface.php',
|
209 |
+
'Psr\\Cache\\CacheItemPoolInterface' => $vendorDir . '/psr/cache/src/CacheItemPoolInterface.php',
|
210 |
+
'Psr\\Cache\\InvalidArgumentException' => $vendorDir . '/psr/cache/src/InvalidArgumentException.php',
|
211 |
+
'Psr\\Http\\Message\\MessageInterface' => $vendorDir . '/psr/http-message/src/MessageInterface.php',
|
212 |
+
'Psr\\Http\\Message\\RequestInterface' => $vendorDir . '/psr/http-message/src/RequestInterface.php',
|
213 |
+
'Psr\\Http\\Message\\ResponseInterface' => $vendorDir . '/psr/http-message/src/ResponseInterface.php',
|
214 |
+
'Psr\\Http\\Message\\ServerRequestInterface' => $vendorDir . '/psr/http-message/src/ServerRequestInterface.php',
|
215 |
+
'Psr\\Http\\Message\\StreamInterface' => $vendorDir . '/psr/http-message/src/StreamInterface.php',
|
216 |
+
'Psr\\Http\\Message\\UploadedFileInterface' => $vendorDir . '/psr/http-message/src/UploadedFileInterface.php',
|
217 |
+
'Psr\\Http\\Message\\UriInterface' => $vendorDir . '/psr/http-message/src/UriInterface.php',
|
218 |
+
'Psr\\Log\\AbstractLogger' => $vendorDir . '/psr/log/Psr/Log/AbstractLogger.php',
|
219 |
+
'Psr\\Log\\InvalidArgumentException' => $vendorDir . '/psr/log/Psr/Log/InvalidArgumentException.php',
|
220 |
+
'Psr\\Log\\LogLevel' => $vendorDir . '/psr/log/Psr/Log/LogLevel.php',
|
221 |
+
'Psr\\Log\\LoggerAwareInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerAwareInterface.php',
|
222 |
+
'Psr\\Log\\LoggerAwareTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerAwareTrait.php',
|
223 |
+
'Psr\\Log\\LoggerInterface' => $vendorDir . '/psr/log/Psr/Log/LoggerInterface.php',
|
224 |
+
'Psr\\Log\\LoggerTrait' => $vendorDir . '/psr/log/Psr/Log/LoggerTrait.php',
|
225 |
+
'Psr\\Log\\NullLogger' => $vendorDir . '/psr/log/Psr/Log/NullLogger.php',
|
226 |
+
'phpseclib\\Crypt\\AES' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/AES.php',
|
227 |
+
'phpseclib\\Crypt\\Base' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Base.php',
|
228 |
+
'phpseclib\\Crypt\\Blowfish' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php',
|
229 |
+
'phpseclib\\Crypt\\DES' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/DES.php',
|
230 |
+
'phpseclib\\Crypt\\Hash' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Hash.php',
|
231 |
+
'phpseclib\\Crypt\\RC2' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RC2.php',
|
232 |
+
'phpseclib\\Crypt\\RC4' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RC4.php',
|
233 |
+
'phpseclib\\Crypt\\RSA' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/RSA.php',
|
234 |
+
'phpseclib\\Crypt\\Random' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Random.php',
|
235 |
+
'phpseclib\\Crypt\\Rijndael' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php',
|
236 |
+
'phpseclib\\Crypt\\TripleDES' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php',
|
237 |
+
'phpseclib\\Crypt\\Twofish' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php',
|
238 |
+
'phpseclib\\Math\\BigInteger' => $vendorDir . '/phpseclib/phpseclib/phpseclib/Math/BigInteger.php',
|
239 |
);
|
vendor/composer/autoload_real.php
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
-
class
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
@@ -19,48 +19,39 @@ class ComposerAutoloaderInit07e98588aa3894ff9e3dc547d403ad69
|
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
-
spl_autoload_register(array('
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
-
spl_autoload_unregister(array('
|
25 |
|
26 |
-
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION');
|
27 |
if ($useStaticLoader) {
|
28 |
require_once __DIR__ . '/autoload_static.php';
|
29 |
|
30 |
-
call_user_func(\Composer\Autoload\
|
31 |
} else {
|
32 |
-
$map = require __DIR__ . '/autoload_namespaces.php';
|
33 |
-
foreach ($map as $namespace => $path) {
|
34 |
-
$loader->set($namespace, $path);
|
35 |
-
}
|
36 |
-
|
37 |
-
$map = require __DIR__ . '/autoload_psr4.php';
|
38 |
-
foreach ($map as $namespace => $path) {
|
39 |
-
$loader->setPsr4($namespace, $path);
|
40 |
-
}
|
41 |
-
|
42 |
$classMap = require __DIR__ . '/autoload_classmap.php';
|
43 |
if ($classMap) {
|
44 |
$loader->addClassMap($classMap);
|
45 |
}
|
46 |
}
|
47 |
|
|
|
48 |
$loader->register(false);
|
49 |
|
50 |
if ($useStaticLoader) {
|
51 |
-
$includeFiles = Composer\Autoload\
|
52 |
} else {
|
53 |
$includeFiles = require __DIR__ . '/autoload_files.php';
|
54 |
}
|
55 |
foreach ($includeFiles as $fileIdentifier => $file) {
|
56 |
-
|
57 |
}
|
58 |
|
59 |
return $loader;
|
60 |
}
|
61 |
}
|
62 |
|
63 |
-
function
|
64 |
{
|
65 |
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
66 |
require $file;
|
2 |
|
3 |
// autoload_real.php @generated by Composer
|
4 |
|
5 |
+
class ComposerAutoloaderInitbd625bfb904527ebcdc364a59295e538
|
6 |
{
|
7 |
private static $loader;
|
8 |
|
19 |
return self::$loader;
|
20 |
}
|
21 |
|
22 |
+
spl_autoload_register(array('ComposerAutoloaderInitbd625bfb904527ebcdc364a59295e538', 'loadClassLoader'), true, false);
|
23 |
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
24 |
+
spl_autoload_unregister(array('ComposerAutoloaderInitbd625bfb904527ebcdc364a59295e538', 'loadClassLoader'));
|
25 |
|
26 |
+
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
27 |
if ($useStaticLoader) {
|
28 |
require_once __DIR__ . '/autoload_static.php';
|
29 |
|
30 |
+
call_user_func(\Composer\Autoload\ComposerStaticInitbd625bfb904527ebcdc364a59295e538::getInitializer($loader));
|
31 |
} else {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
$classMap = require __DIR__ . '/autoload_classmap.php';
|
33 |
if ($classMap) {
|
34 |
$loader->addClassMap($classMap);
|
35 |
}
|
36 |
}
|
37 |
|
38 |
+
$loader->setClassMapAuthoritative(true);
|
39 |
$loader->register(false);
|
40 |
|
41 |
if ($useStaticLoader) {
|
42 |
+
$includeFiles = Composer\Autoload\ComposerStaticInitbd625bfb904527ebcdc364a59295e538::$files;
|
43 |
} else {
|
44 |
$includeFiles = require __DIR__ . '/autoload_files.php';
|
45 |
}
|
46 |
foreach ($includeFiles as $fileIdentifier => $file) {
|
47 |
+
composerRequirebd625bfb904527ebcdc364a59295e538($fileIdentifier, $file);
|
48 |
}
|
49 |
|
50 |
return $loader;
|
51 |
}
|
52 |
}
|
53 |
|
54 |
+
function composerRequirebd625bfb904527ebcdc364a59295e538($fileIdentifier, $file)
|
55 |
{
|
56 |
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
57 |
require $file;
|
vendor/composer/autoload_static.php
CHANGED
@@ -4,7 +4,7 @@
|
|
4 |
|
5 |
namespace Composer\Autoload;
|
6 |
|
7 |
-
class
|
8 |
{
|
9 |
public static $files = array (
|
10 |
'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
|
@@ -121,17 +121,245 @@ class ComposerStaticInit07e98588aa3894ff9e3dc547d403ad69
|
|
121 |
);
|
122 |
|
123 |
public static $classMap = array (
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
124 |
'Google_Service_Exception' => __DIR__ . '/..' . '/google/apiclient/src/Google/Service/Exception.php',
|
125 |
'Google_Service_Resource' => __DIR__ . '/..' . '/google/apiclient/src/Google/Service/Resource.php',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
);
|
127 |
|
128 |
public static function getInitializer(ClassLoader $loader)
|
129 |
{
|
130 |
return \Closure::bind(function () use ($loader) {
|
131 |
-
$loader->prefixLengthsPsr4 =
|
132 |
-
$loader->prefixDirsPsr4 =
|
133 |
-
$loader->prefixesPsr0 =
|
134 |
-
$loader->classMap =
|
135 |
|
136 |
}, null, ClassLoader::class);
|
137 |
}
|
4 |
|
5 |
namespace Composer\Autoload;
|
6 |
|
7 |
+
class ComposerStaticInitbd625bfb904527ebcdc364a59295e538
|
8 |
{
|
9 |
public static $files = array (
|
10 |
'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
|
121 |
);
|
122 |
|
123 |
public static $classMap = array (
|
124 |
+
'Google\\Auth\\ApplicationDefaultCredentials' => __DIR__ . '/..' . '/google/auth/src/ApplicationDefaultCredentials.php',
|
125 |
+
'Google\\Auth\\CacheTrait' => __DIR__ . '/..' . '/google/auth/src/CacheTrait.php',
|
126 |
+
'Google\\Auth\\Cache\\InvalidArgumentException' => __DIR__ . '/..' . '/google/auth/src/Cache/InvalidArgumentException.php',
|
127 |
+
'Google\\Auth\\Cache\\Item' => __DIR__ . '/..' . '/google/auth/src/Cache/Item.php',
|
128 |
+
'Google\\Auth\\Cache\\MemoryCacheItemPool' => __DIR__ . '/..' . '/google/auth/src/Cache/MemoryCacheItemPool.php',
|
129 |
+
'Google\\Auth\\CredentialsLoader' => __DIR__ . '/..' . '/google/auth/src/CredentialsLoader.php',
|
130 |
+
'Google\\Auth\\Credentials\\AppIdentityCredentials' => __DIR__ . '/..' . '/google/auth/src/Credentials/AppIdentityCredentials.php',
|
131 |
+
'Google\\Auth\\Credentials\\GCECredentials' => __DIR__ . '/..' . '/google/auth/src/Credentials/GCECredentials.php',
|
132 |
+
'Google\\Auth\\Credentials\\IAMCredentials' => __DIR__ . '/..' . '/google/auth/src/Credentials/IAMCredentials.php',
|
133 |
+
'Google\\Auth\\Credentials\\ServiceAccountCredentials' => __DIR__ . '/..' . '/google/auth/src/Credentials/ServiceAccountCredentials.php',
|
134 |
+
'Google\\Auth\\Credentials\\ServiceAccountJwtAccessCredentials' => __DIR__ . '/..' . '/google/auth/src/Credentials/ServiceAccountJwtAccessCredentials.php',
|
135 |
+
'Google\\Auth\\Credentials\\UserRefreshCredentials' => __DIR__ . '/..' . '/google/auth/src/Credentials/UserRefreshCredentials.php',
|
136 |
+
'Google\\Auth\\FetchAuthTokenCache' => __DIR__ . '/..' . '/google/auth/src/FetchAuthTokenCache.php',
|
137 |
+
'Google\\Auth\\FetchAuthTokenInterface' => __DIR__ . '/..' . '/google/auth/src/FetchAuthTokenInterface.php',
|
138 |
+
'Google\\Auth\\HttpHandler\\Guzzle5HttpHandler' => __DIR__ . '/..' . '/google/auth/src/HttpHandler/Guzzle5HttpHandler.php',
|
139 |
+
'Google\\Auth\\HttpHandler\\Guzzle6HttpHandler' => __DIR__ . '/..' . '/google/auth/src/HttpHandler/Guzzle6HttpHandler.php',
|
140 |
+
'Google\\Auth\\HttpHandler\\HttpHandlerFactory' => __DIR__ . '/..' . '/google/auth/src/HttpHandler/HttpHandlerFactory.php',
|
141 |
+
'Google\\Auth\\Middleware\\AuthTokenMiddleware' => __DIR__ . '/..' . '/google/auth/src/Middleware/AuthTokenMiddleware.php',
|
142 |
+
'Google\\Auth\\Middleware\\ScopedAccessTokenMiddleware' => __DIR__ . '/..' . '/google/auth/src/Middleware/ScopedAccessTokenMiddleware.php',
|
143 |
+
'Google\\Auth\\Middleware\\SimpleMiddleware' => __DIR__ . '/..' . '/google/auth/src/Middleware/SimpleMiddleware.php',
|
144 |
+
'Google\\Auth\\OAuth2' => __DIR__ . '/..' . '/google/auth/src/OAuth2.php',
|
145 |
+
'Google\\Auth\\Subscriber\\AuthTokenSubscriber' => __DIR__ . '/..' . '/google/auth/src/Subscriber/AuthTokenSubscriber.php',
|
146 |
+
'Google\\Auth\\Subscriber\\ScopedAccessTokenSubscriber' => __DIR__ . '/..' . '/google/auth/src/Subscriber/ScopedAccessTokenSubscriber.php',
|
147 |
+
'Google\\Auth\\Subscriber\\SimpleSubscriber' => __DIR__ . '/..' . '/google/auth/src/Subscriber/SimpleSubscriber.php',
|
148 |
+
'Google_AccessToken_Revoke' => __DIR__ . '/..' . '/google/apiclient/src/Google/AccessToken/Revoke.php',
|
149 |
+
'Google_AccessToken_Verify' => __DIR__ . '/..' . '/google/apiclient/src/Google/AccessToken/Verify.php',
|
150 |
+
'Google_AuthHandler_AuthHandlerFactory' => __DIR__ . '/..' . '/google/apiclient/src/Google/AuthHandler/AuthHandlerFactory.php',
|
151 |
+
'Google_AuthHandler_Guzzle5AuthHandler' => __DIR__ . '/..' . '/google/apiclient/src/Google/AuthHandler/Guzzle5AuthHandler.php',
|
152 |
+
'Google_AuthHandler_Guzzle6AuthHandler' => __DIR__ . '/..' . '/google/apiclient/src/Google/AuthHandler/Guzzle6AuthHandler.php',
|
153 |
+
'Google_Client' => __DIR__ . '/..' . '/google/apiclient/src/Google/Client.php',
|
154 |
+
'Google_Collection' => __DIR__ . '/..' . '/google/apiclient/src/Google/Collection.php',
|
155 |
+
'Google_Exception' => __DIR__ . '/..' . '/google/apiclient/src/Google/Exception.php',
|
156 |
+
'Google_Http_Batch' => __DIR__ . '/..' . '/google/apiclient/src/Google/Http/Batch.php',
|
157 |
+
'Google_Http_MediaFileUpload' => __DIR__ . '/..' . '/google/apiclient/src/Google/Http/MediaFileUpload.php',
|
158 |
+
'Google_Http_REST' => __DIR__ . '/..' . '/google/apiclient/src/Google/Http/REST.php',
|
159 |
+
'Google_Model' => __DIR__ . '/..' . '/google/apiclient/src/Google/Model.php',
|
160 |
+
'Google_Service' => __DIR__ . '/..' . '/google/apiclient/src/Google/Service.php',
|
161 |
'Google_Service_Exception' => __DIR__ . '/..' . '/google/apiclient/src/Google/Service/Exception.php',
|
162 |
'Google_Service_Resource' => __DIR__ . '/..' . '/google/apiclient/src/Google/Service/Resource.php',
|
163 |
+
'Google_Task_Exception' => __DIR__ . '/..' . '/google/apiclient/src/Google/Task/Exception.php',
|
164 |
+
'Google_Task_Retryable' => __DIR__ . '/..' . '/google/apiclient/src/Google/Task/Retryable.php',
|
165 |
+
'Google_Task_Runner' => __DIR__ . '/..' . '/google/apiclient/src/Google/Task/Runner.php',
|
166 |
+
'Google_Utils_UriTemplate' => __DIR__ . '/..' . '/google/apiclient/src/Google/Utils/UriTemplate.php',
|
167 |
+
'GuzzleHttp\\Client' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Client.php',
|
168 |
+
'GuzzleHttp\\ClientInterface' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/ClientInterface.php',
|
169 |
+
'GuzzleHttp\\Cookie\\CookieJar' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Cookie/CookieJar.php',
|
170 |
+
'GuzzleHttp\\Cookie\\CookieJarInterface' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php',
|
171 |
+
'GuzzleHttp\\Cookie\\FileCookieJar' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php',
|
172 |
+
'GuzzleHttp\\Cookie\\SessionCookieJar' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php',
|
173 |
+
'GuzzleHttp\\Cookie\\SetCookie' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Cookie/SetCookie.php',
|
174 |
+
'GuzzleHttp\\Exception\\BadResponseException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/BadResponseException.php',
|
175 |
+
'GuzzleHttp\\Exception\\ClientException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/ClientException.php',
|
176 |
+
'GuzzleHttp\\Exception\\ConnectException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/ConnectException.php',
|
177 |
+
'GuzzleHttp\\Exception\\GuzzleException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/GuzzleException.php',
|
178 |
+
'GuzzleHttp\\Exception\\RequestException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/RequestException.php',
|
179 |
+
'GuzzleHttp\\Exception\\SeekException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/SeekException.php',
|
180 |
+
'GuzzleHttp\\Exception\\ServerException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/ServerException.php',
|
181 |
+
'GuzzleHttp\\Exception\\TooManyRedirectsException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php',
|
182 |
+
'GuzzleHttp\\Exception\\TransferException' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Exception/TransferException.php',
|
183 |
+
'GuzzleHttp\\HandlerStack' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/HandlerStack.php',
|
184 |
+
'GuzzleHttp\\Handler\\CurlFactory' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/CurlFactory.php',
|
185 |
+
'GuzzleHttp\\Handler\\CurlFactoryInterface' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php',
|
186 |
+
'GuzzleHttp\\Handler\\CurlHandler' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/CurlHandler.php',
|
187 |
+
'GuzzleHttp\\Handler\\CurlMultiHandler' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php',
|
188 |
+
'GuzzleHttp\\Handler\\EasyHandle' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/EasyHandle.php',
|
189 |
+
'GuzzleHttp\\Handler\\MockHandler' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/MockHandler.php',
|
190 |
+
'GuzzleHttp\\Handler\\Proxy' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/Proxy.php',
|
191 |
+
'GuzzleHttp\\Handler\\StreamHandler' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Handler/StreamHandler.php',
|
192 |
+
'GuzzleHttp\\MessageFormatter' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/MessageFormatter.php',
|
193 |
+
'GuzzleHttp\\Middleware' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Middleware.php',
|
194 |
+
'GuzzleHttp\\Pool' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/Pool.php',
|
195 |
+
'GuzzleHttp\\PrepareBodyMiddleware' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php',
|
196 |
+
'GuzzleHttp\\Promise\\AggregateException' => __DIR__ . '/..' . '/guzzlehttp/promises/src/AggregateException.php',
|
197 |
+
'GuzzleHttp\\Promise\\CancellationException' => __DIR__ . '/..' . '/guzzlehttp/promises/src/CancellationException.php',
|
198 |
+
'GuzzleHttp\\Promise\\Coroutine' => __DIR__ . '/..' . '/guzzlehttp/promises/src/Coroutine.php',
|
199 |
+
'GuzzleHttp\\Promise\\EachPromise' => __DIR__ . '/..' . '/guzzlehttp/promises/src/EachPromise.php',
|
200 |
+
'GuzzleHttp\\Promise\\FulfilledPromise' => __DIR__ . '/..' . '/guzzlehttp/promises/src/FulfilledPromise.php',
|
201 |
+
'GuzzleHttp\\Promise\\Promise' => __DIR__ . '/..' . '/guzzlehttp/promises/src/Promise.php',
|
202 |
+
'GuzzleHttp\\Promise\\PromiseInterface' => __DIR__ . '/..' . '/guzzlehttp/promises/src/PromiseInterface.php',
|
203 |
+
'GuzzleHttp\\Promise\\PromisorInterface' => __DIR__ . '/..' . '/guzzlehttp/promises/src/PromisorInterface.php',
|
204 |
+
'GuzzleHttp\\Promise\\RejectedPromise' => __DIR__ . '/..' . '/guzzlehttp/promises/src/RejectedPromise.php',
|
205 |
+
'GuzzleHttp\\Promise\\RejectionException' => __DIR__ . '/..' . '/guzzlehttp/promises/src/RejectionException.php',
|
206 |
+
'GuzzleHttp\\Promise\\TaskQueue' => __DIR__ . '/..' . '/guzzlehttp/promises/src/TaskQueue.php',
|
207 |
+
'GuzzleHttp\\Promise\\TaskQueueInterface' => __DIR__ . '/..' . '/guzzlehttp/promises/src/TaskQueueInterface.php',
|
208 |
+
'GuzzleHttp\\Psr7\\AppendStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/AppendStream.php',
|
209 |
+
'GuzzleHttp\\Psr7\\BufferStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/BufferStream.php',
|
210 |
+
'GuzzleHttp\\Psr7\\CachingStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/CachingStream.php',
|
211 |
+
'GuzzleHttp\\Psr7\\DroppingStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/DroppingStream.php',
|
212 |
+
'GuzzleHttp\\Psr7\\FnStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/FnStream.php',
|
213 |
+
'GuzzleHttp\\Psr7\\InflateStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/InflateStream.php',
|
214 |
+
'GuzzleHttp\\Psr7\\LazyOpenStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/LazyOpenStream.php',
|
215 |
+
'GuzzleHttp\\Psr7\\LimitStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/LimitStream.php',
|
216 |
+
'GuzzleHttp\\Psr7\\MessageTrait' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/MessageTrait.php',
|
217 |
+
'GuzzleHttp\\Psr7\\MultipartStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/MultipartStream.php',
|
218 |
+
'GuzzleHttp\\Psr7\\NoSeekStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/NoSeekStream.php',
|
219 |
+
'GuzzleHttp\\Psr7\\PumpStream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/PumpStream.php',
|
220 |
+
'GuzzleHttp\\Psr7\\Request' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Request.php',
|
221 |
+
'GuzzleHttp\\Psr7\\Response' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Response.php',
|
222 |
+
'GuzzleHttp\\Psr7\\ServerRequest' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/ServerRequest.php',
|
223 |
+
'GuzzleHttp\\Psr7\\Stream' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Stream.php',
|
224 |
+
'GuzzleHttp\\Psr7\\StreamDecoratorTrait' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/StreamDecoratorTrait.php',
|
225 |
+
'GuzzleHttp\\Psr7\\StreamWrapper' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/StreamWrapper.php',
|
226 |
+
'GuzzleHttp\\Psr7\\UploadedFile' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/UploadedFile.php',
|
227 |
+
'GuzzleHttp\\Psr7\\Uri' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/Uri.php',
|
228 |
+
'GuzzleHttp\\Psr7\\UriNormalizer' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/UriNormalizer.php',
|
229 |
+
'GuzzleHttp\\Psr7\\UriResolver' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/UriResolver.php',
|
230 |
+
'GuzzleHttp\\RedirectMiddleware' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/RedirectMiddleware.php',
|
231 |
+
'GuzzleHttp\\RequestOptions' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/RequestOptions.php',
|
232 |
+
'GuzzleHttp\\RetryMiddleware' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/RetryMiddleware.php',
|
233 |
+
'GuzzleHttp\\TransferStats' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/TransferStats.php',
|
234 |
+
'GuzzleHttp\\UriTemplate' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/UriTemplate.php',
|
235 |
+
'Monolog\\ErrorHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/ErrorHandler.php',
|
236 |
+
'Monolog\\Formatter\\ChromePHPFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php',
|
237 |
+
'Monolog\\Formatter\\ElasticaFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php',
|
238 |
+
'Monolog\\Formatter\\FlowdockFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php',
|
239 |
+
'Monolog\\Formatter\\FluentdFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php',
|
240 |
+
'Monolog\\Formatter\\FormatterInterface' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/FormatterInterface.php',
|
241 |
+
'Monolog\\Formatter\\GelfMessageFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php',
|
242 |
+
'Monolog\\Formatter\\HtmlFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php',
|
243 |
+
'Monolog\\Formatter\\JsonFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/JsonFormatter.php',
|
244 |
+
'Monolog\\Formatter\\LineFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/LineFormatter.php',
|
245 |
+
'Monolog\\Formatter\\LogglyFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php',
|
246 |
+
'Monolog\\Formatter\\LogstashFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php',
|
247 |
+
'Monolog\\Formatter\\MongoDBFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php',
|
248 |
+
'Monolog\\Formatter\\NormalizerFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php',
|
249 |
+
'Monolog\\Formatter\\ScalarFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php',
|
250 |
+
'Monolog\\Formatter\\WildfireFormatter' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php',
|
251 |
+
'Monolog\\Handler\\AbstractHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/AbstractHandler.php',
|
252 |
+
'Monolog\\Handler\\AbstractProcessingHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php',
|
253 |
+
'Monolog\\Handler\\AbstractSyslogHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php',
|
254 |
+
'Monolog\\Handler\\AmqpHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/AmqpHandler.php',
|
255 |
+
'Monolog\\Handler\\BrowserConsoleHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php',
|
256 |
+
'Monolog\\Handler\\BufferHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/BufferHandler.php',
|
257 |
+
'Monolog\\Handler\\ChromePHPHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php',
|
258 |
+
'Monolog\\Handler\\CouchDBHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/CouchDBHandler.php',
|
259 |
+
'Monolog\\Handler\\CubeHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/CubeHandler.php',
|
260 |
+
'Monolog\\Handler\\Curl\\Util' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/Curl/Util.php',
|
261 |
+
'Monolog\\Handler\\DeduplicationHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php',
|
262 |
+
'Monolog\\Handler\\DoctrineCouchDBHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php',
|
263 |
+
'Monolog\\Handler\\DynamoDbHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php',
|
264 |
+
'Monolog\\Handler\\ElasticSearchHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ElasticSearchHandler.php',
|
265 |
+
'Monolog\\Handler\\ErrorLogHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php',
|
266 |
+
'Monolog\\Handler\\FilterHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FilterHandler.php',
|
267 |
+
'Monolog\\Handler\\FingersCrossedHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php',
|
268 |
+
'Monolog\\Handler\\FingersCrossed\\ActivationStrategyInterface' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php',
|
269 |
+
'Monolog\\Handler\\FingersCrossed\\ChannelLevelActivationStrategy' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php',
|
270 |
+
'Monolog\\Handler\\FingersCrossed\\ErrorLevelActivationStrategy' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php',
|
271 |
+
'Monolog\\Handler\\FirePHPHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php',
|
272 |
+
'Monolog\\Handler\\FleepHookHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FleepHookHandler.php',
|
273 |
+
'Monolog\\Handler\\FlowdockHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php',
|
274 |
+
'Monolog\\Handler\\GelfHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/GelfHandler.php',
|
275 |
+
'Monolog\\Handler\\GroupHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/GroupHandler.php',
|
276 |
+
'Monolog\\Handler\\HandlerInterface' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/HandlerInterface.php',
|
277 |
+
'Monolog\\Handler\\HandlerWrapper' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/HandlerWrapper.php',
|
278 |
+
'Monolog\\Handler\\HipChatHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/HipChatHandler.php',
|
279 |
+
'Monolog\\Handler\\IFTTTHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php',
|
280 |
+
'Monolog\\Handler\\LogEntriesHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php',
|
281 |
+
'Monolog\\Handler\\LogglyHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/LogglyHandler.php',
|
282 |
+
'Monolog\\Handler\\MailHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/MailHandler.php',
|
283 |
+
'Monolog\\Handler\\MandrillHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/MandrillHandler.php',
|
284 |
+
'Monolog\\Handler\\MissingExtensionException' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/MissingExtensionException.php',
|
285 |
+
'Monolog\\Handler\\MongoDBHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/MongoDBHandler.php',
|
286 |
+
'Monolog\\Handler\\NativeMailerHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php',
|
287 |
+
'Monolog\\Handler\\NewRelicHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/NewRelicHandler.php',
|
288 |
+
'Monolog\\Handler\\NullHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/NullHandler.php',
|
289 |
+
'Monolog\\Handler\\PHPConsoleHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php',
|
290 |
+
'Monolog\\Handler\\PsrHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/PsrHandler.php',
|
291 |
+
'Monolog\\Handler\\PushoverHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/PushoverHandler.php',
|
292 |
+
'Monolog\\Handler\\RavenHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/RavenHandler.php',
|
293 |
+
'Monolog\\Handler\\RedisHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/RedisHandler.php',
|
294 |
+
'Monolog\\Handler\\RollbarHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/RollbarHandler.php',
|
295 |
+
'Monolog\\Handler\\RotatingFileHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php',
|
296 |
+
'Monolog\\Handler\\SamplingHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SamplingHandler.php',
|
297 |
+
'Monolog\\Handler\\SlackHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SlackHandler.php',
|
298 |
+
'Monolog\\Handler\\SlackWebhookHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php',
|
299 |
+
'Monolog\\Handler\\Slack\\SlackRecord' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php',
|
300 |
+
'Monolog\\Handler\\SlackbotHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SlackbotHandler.php',
|
301 |
+
'Monolog\\Handler\\SocketHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SocketHandler.php',
|
302 |
+
'Monolog\\Handler\\StreamHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/StreamHandler.php',
|
303 |
+
'Monolog\\Handler\\SwiftMailerHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php',
|
304 |
+
'Monolog\\Handler\\SyslogHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SyslogHandler.php',
|
305 |
+
'Monolog\\Handler\\SyslogUdpHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php',
|
306 |
+
'Monolog\\Handler\\SyslogUdp\\UdpSocket' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php',
|
307 |
+
'Monolog\\Handler\\WhatFailureGroupHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php',
|
308 |
+
'Monolog\\Handler\\ZendMonitorHandler' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php',
|
309 |
+
'Monolog\\Logger' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Logger.php',
|
310 |
+
'Monolog\\Processor\\GitProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/GitProcessor.php',
|
311 |
+
'Monolog\\Processor\\IntrospectionProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php',
|
312 |
+
'Monolog\\Processor\\MemoryPeakUsageProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php',
|
313 |
+
'Monolog\\Processor\\MemoryProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php',
|
314 |
+
'Monolog\\Processor\\MemoryUsageProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php',
|
315 |
+
'Monolog\\Processor\\MercurialProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php',
|
316 |
+
'Monolog\\Processor\\ProcessIdProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php',
|
317 |
+
'Monolog\\Processor\\PsrLogMessageProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php',
|
318 |
+
'Monolog\\Processor\\TagProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/TagProcessor.php',
|
319 |
+
'Monolog\\Processor\\UidProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/UidProcessor.php',
|
320 |
+
'Monolog\\Processor\\WebProcessor' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Processor/WebProcessor.php',
|
321 |
+
'Monolog\\Registry' => __DIR__ . '/..' . '/monolog/monolog/src/Monolog/Registry.php',
|
322 |
+
'Psr\\Cache\\CacheException' => __DIR__ . '/..' . '/psr/cache/src/CacheException.php',
|
323 |
+
'Psr\\Cache\\CacheItemInterface' => __DIR__ . '/..' . '/psr/cache/src/CacheItemInterface.php',
|
324 |
+
'Psr\\Cache\\CacheItemPoolInterface' => __DIR__ . '/..' . '/psr/cache/src/CacheItemPoolInterface.php',
|
325 |
+
'Psr\\Cache\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/cache/src/InvalidArgumentException.php',
|
326 |
+
'Psr\\Http\\Message\\MessageInterface' => __DIR__ . '/..' . '/psr/http-message/src/MessageInterface.php',
|
327 |
+
'Psr\\Http\\Message\\RequestInterface' => __DIR__ . '/..' . '/psr/http-message/src/RequestInterface.php',
|
328 |
+
'Psr\\Http\\Message\\ResponseInterface' => __DIR__ . '/..' . '/psr/http-message/src/ResponseInterface.php',
|
329 |
+
'Psr\\Http\\Message\\ServerRequestInterface' => __DIR__ . '/..' . '/psr/http-message/src/ServerRequestInterface.php',
|
330 |
+
'Psr\\Http\\Message\\StreamInterface' => __DIR__ . '/..' . '/psr/http-message/src/StreamInterface.php',
|
331 |
+
'Psr\\Http\\Message\\UploadedFileInterface' => __DIR__ . '/..' . '/psr/http-message/src/UploadedFileInterface.php',
|
332 |
+
'Psr\\Http\\Message\\UriInterface' => __DIR__ . '/..' . '/psr/http-message/src/UriInterface.php',
|
333 |
+
'Psr\\Log\\AbstractLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/AbstractLogger.php',
|
334 |
+
'Psr\\Log\\InvalidArgumentException' => __DIR__ . '/..' . '/psr/log/Psr/Log/InvalidArgumentException.php',
|
335 |
+
'Psr\\Log\\LogLevel' => __DIR__ . '/..' . '/psr/log/Psr/Log/LogLevel.php',
|
336 |
+
'Psr\\Log\\LoggerAwareInterface' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerAwareInterface.php',
|
337 |
+
'Psr\\Log\\LoggerAwareTrait' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerAwareTrait.php',
|
338 |
+
'Psr\\Log\\LoggerInterface' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerInterface.php',
|
339 |
+
'Psr\\Log\\LoggerTrait' => __DIR__ . '/..' . '/psr/log/Psr/Log/LoggerTrait.php',
|
340 |
+
'Psr\\Log\\NullLogger' => __DIR__ . '/..' . '/psr/log/Psr/Log/NullLogger.php',
|
341 |
+
'phpseclib\\Crypt\\AES' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/AES.php',
|
342 |
+
'phpseclib\\Crypt\\Base' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Base.php',
|
343 |
+
'phpseclib\\Crypt\\Blowfish' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php',
|
344 |
+
'phpseclib\\Crypt\\DES' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/DES.php',
|
345 |
+
'phpseclib\\Crypt\\Hash' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Hash.php',
|
346 |
+
'phpseclib\\Crypt\\RC2' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RC2.php',
|
347 |
+
'phpseclib\\Crypt\\RC4' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RC4.php',
|
348 |
+
'phpseclib\\Crypt\\RSA' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/RSA.php',
|
349 |
+
'phpseclib\\Crypt\\Random' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Random.php',
|
350 |
+
'phpseclib\\Crypt\\Rijndael' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php',
|
351 |
+
'phpseclib\\Crypt\\TripleDES' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php',
|
352 |
+
'phpseclib\\Crypt\\Twofish' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php',
|
353 |
+
'phpseclib\\Math\\BigInteger' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/Math/BigInteger.php',
|
354 |
);
|
355 |
|
356 |
public static function getInitializer(ClassLoader $loader)
|
357 |
{
|
358 |
return \Closure::bind(function () use ($loader) {
|
359 |
+
$loader->prefixLengthsPsr4 = ComposerStaticInitbd625bfb904527ebcdc364a59295e538::$prefixLengthsPsr4;
|
360 |
+
$loader->prefixDirsPsr4 = ComposerStaticInitbd625bfb904527ebcdc364a59295e538::$prefixDirsPsr4;
|
361 |
+
$loader->prefixesPsr0 = ComposerStaticInitbd625bfb904527ebcdc364a59295e538::$prefixesPsr0;
|
362 |
+
$loader->classMap = ComposerStaticInitbd625bfb904527ebcdc364a59295e538::$classMap;
|
363 |
|
364 |
}, null, ClassLoader::class);
|
365 |
}
|
vendor/phpseclib/phpseclib/phpseclib/Crypt/Base.php
DELETED
@@ -1,2558 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Base Class for all \phpseclib\Crypt\* cipher classes
|
5 |
-
*
|
6 |
-
* PHP version 5
|
7 |
-
*
|
8 |
-
* Internally for phpseclib developers:
|
9 |
-
* If you plan to add a new cipher class, please note following rules:
|
10 |
-
*
|
11 |
-
* - The new \phpseclib\Crypt\* cipher class should extend \phpseclib\Crypt\Base
|
12 |
-
*
|
13 |
-
* - Following methods are then required to be overridden/overloaded:
|
14 |
-
*
|
15 |
-
* - _encryptBlock()
|
16 |
-
*
|
17 |
-
* - _decryptBlock()
|
18 |
-
*
|
19 |
-
* - _setupKey()
|
20 |
-
*
|
21 |
-
* - All other methods are optional to be overridden/overloaded
|
22 |
-
*
|
23 |
-
* - Look at the source code of the current ciphers how they extend \phpseclib\Crypt\Base
|
24 |
-
* and take one of them as a start up for the new cipher class.
|
25 |
-
*
|
26 |
-
* - Please read all the other comments/notes/hints here also for each class var/method
|
27 |
-
*
|
28 |
-
* @category Crypt
|
29 |
-
* @package Base
|
30 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
31 |
-
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
|
32 |
-
* @copyright 2007 Jim Wigginton
|
33 |
-
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
34 |
-
* @link http://phpseclib.sourceforge.net
|
35 |
-
*/
|
36 |
-
|
37 |
-
namespace phpseclib\Crypt;
|
38 |
-
|
39 |
-
/**
|
40 |
-
* Base Class for all \phpseclib\Crypt\* cipher classes
|
41 |
-
*
|
42 |
-
* @package Base
|
43 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
44 |
-
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
|
45 |
-
*/
|
46 |
-
abstract class Base
|
47 |
-
{
|
48 |
-
/**#@+
|
49 |
-
* @access public
|
50 |
-
* @see \phpseclib\Crypt\Base::encrypt()
|
51 |
-
* @see \phpseclib\Crypt\Base::decrypt()
|
52 |
-
*/
|
53 |
-
/**
|
54 |
-
* Encrypt / decrypt using the Counter mode.
|
55 |
-
*
|
56 |
-
* Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
|
57 |
-
*
|
58 |
-
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
|
59 |
-
*/
|
60 |
-
const MODE_CTR = -1;
|
61 |
-
/**
|
62 |
-
* Encrypt / decrypt using the Electronic Code Book mode.
|
63 |
-
*
|
64 |
-
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
|
65 |
-
*/
|
66 |
-
const MODE_ECB = 1;
|
67 |
-
/**
|
68 |
-
* Encrypt / decrypt using the Code Book Chaining mode.
|
69 |
-
*
|
70 |
-
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
|
71 |
-
*/
|
72 |
-
const MODE_CBC = 2;
|
73 |
-
/**
|
74 |
-
* Encrypt / decrypt using the Cipher Feedback mode.
|
75 |
-
*
|
76 |
-
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
|
77 |
-
*/
|
78 |
-
const MODE_CFB = 3;
|
79 |
-
/**
|
80 |
-
* Encrypt / decrypt using the Output Feedback mode.
|
81 |
-
*
|
82 |
-
* @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
|
83 |
-
*/
|
84 |
-
const MODE_OFB = 4;
|
85 |
-
/**
|
86 |
-
* Encrypt / decrypt using streaming mode.
|
87 |
-
*/
|
88 |
-
const MODE_STREAM = 5;
|
89 |
-
/**#@-*/
|
90 |
-
|
91 |
-
/**
|
92 |
-
* Whirlpool available flag
|
93 |
-
*
|
94 |
-
* @see \phpseclib\Crypt\Base::_hashInlineCryptFunction()
|
95 |
-
* @var bool
|
96 |
-
* @access private
|
97 |
-
*/
|
98 |
-
static $WHIRLPOOL_AVAILABLE;
|
99 |
-
|
100 |
-
/**#@+
|
101 |
-
* @access private
|
102 |
-
* @see \phpseclib\Crypt\Base::__construct()
|
103 |
-
*/
|
104 |
-
/**
|
105 |
-
* Base value for the internal implementation $engine switch
|
106 |
-
*/
|
107 |
-
const ENGINE_INTERNAL = 1;
|
108 |
-
/**
|
109 |
-
* Base value for the mcrypt implementation $engine switch
|
110 |
-
*/
|
111 |
-
const ENGINE_MCRYPT = 2;
|
112 |
-
/**
|
113 |
-
* Base value for the mcrypt implementation $engine switch
|
114 |
-
*/
|
115 |
-
const ENGINE_OPENSSL = 3;
|
116 |
-
/**#@-*/
|
117 |
-
|
118 |
-
/**
|
119 |
-
* The Encryption Mode
|
120 |
-
*
|
121 |
-
* @see self::__construct()
|
122 |
-
* @var int
|
123 |
-
* @access private
|
124 |
-
*/
|
125 |
-
var $mode;
|
126 |
-
|
127 |
-
/**
|
128 |
-
* The Block Length of the block cipher
|
129 |
-
*
|
130 |
-
* @var int
|
131 |
-
* @access private
|
132 |
-
*/
|
133 |
-
var $block_size = 16;
|
134 |
-
|
135 |
-
/**
|
136 |
-
* The Key
|
137 |
-
*
|
138 |
-
* @see self::setKey()
|
139 |
-
* @var string
|
140 |
-
* @access private
|
141 |
-
*/
|
142 |
-
var $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
|
143 |
-
|
144 |
-
/**
|
145 |
-
* The Initialization Vector
|
146 |
-
*
|
147 |
-
* @see self::setIV()
|
148 |
-
* @var string
|
149 |
-
* @access private
|
150 |
-
*/
|
151 |
-
var $iv;
|
152 |
-
|
153 |
-
/**
|
154 |
-
* A "sliding" Initialization Vector
|
155 |
-
*
|
156 |
-
* @see self::enableContinuousBuffer()
|
157 |
-
* @see self::_clearBuffers()
|
158 |
-
* @var string
|
159 |
-
* @access private
|
160 |
-
*/
|
161 |
-
var $encryptIV;
|
162 |
-
|
163 |
-
/**
|
164 |
-
* A "sliding" Initialization Vector
|
165 |
-
*
|
166 |
-
* @see self::enableContinuousBuffer()
|
167 |
-
* @see self::_clearBuffers()
|
168 |
-
* @var string
|
169 |
-
* @access private
|
170 |
-
*/
|
171 |
-
var $decryptIV;
|
172 |
-
|
173 |
-
/**
|
174 |
-
* Continuous Buffer status
|
175 |
-
*
|
176 |
-
* @see self::enableContinuousBuffer()
|
177 |
-
* @var bool
|
178 |
-
* @access private
|
179 |
-
*/
|
180 |
-
var $continuousBuffer = false;
|
181 |
-
|
182 |
-
/**
|
183 |
-
* Encryption buffer for CTR, OFB and CFB modes
|
184 |
-
*
|
185 |
-
* @see self::encrypt()
|
186 |
-
* @see self::_clearBuffers()
|
187 |
-
* @var array
|
188 |
-
* @access private
|
189 |
-
*/
|
190 |
-
var $enbuffer;
|
191 |
-
|
192 |
-
/**
|
193 |
-
* Decryption buffer for CTR, OFB and CFB modes
|
194 |
-
*
|
195 |
-
* @see self::decrypt()
|
196 |
-
* @see self::_clearBuffers()
|
197 |
-
* @var array
|
198 |
-
* @access private
|
199 |
-
*/
|
200 |
-
var $debuffer;
|
201 |
-
|
202 |
-
/**
|
203 |
-
* mcrypt resource for encryption
|
204 |
-
*
|
205 |
-
* The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
|
206 |
-
* Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
|
207 |
-
*
|
208 |
-
* @see self::encrypt()
|
209 |
-
* @var resource
|
210 |
-
* @access private
|
211 |
-
*/
|
212 |
-
var $enmcrypt;
|
213 |
-
|
214 |
-
/**
|
215 |
-
* mcrypt resource for decryption
|
216 |
-
*
|
217 |
-
* The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
|
218 |
-
* Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
|
219 |
-
*
|
220 |
-
* @see self::decrypt()
|
221 |
-
* @var resource
|
222 |
-
* @access private
|
223 |
-
*/
|
224 |
-
var $demcrypt;
|
225 |
-
|
226 |
-
/**
|
227 |
-
* Does the enmcrypt resource need to be (re)initialized?
|
228 |
-
*
|
229 |
-
* @see \phpseclib\Crypt\Twofish::setKey()
|
230 |
-
* @see \phpseclib\Crypt\Twofish::setIV()
|
231 |
-
* @var bool
|
232 |
-
* @access private
|
233 |
-
*/
|
234 |
-
var $enchanged = true;
|
235 |
-
|
236 |
-
/**
|
237 |
-
* Does the demcrypt resource need to be (re)initialized?
|
238 |
-
*
|
239 |
-
* @see \phpseclib\Crypt\Twofish::setKey()
|
240 |
-
* @see \phpseclib\Crypt\Twofish::setIV()
|
241 |
-
* @var bool
|
242 |
-
* @access private
|
243 |
-
*/
|
244 |
-
var $dechanged = true;
|
245 |
-
|
246 |
-
/**
|
247 |
-
* mcrypt resource for CFB mode
|
248 |
-
*
|
249 |
-
* mcrypt's CFB mode, in (and only in) buffered context,
|
250 |
-
* is broken, so phpseclib implements the CFB mode by it self,
|
251 |
-
* even when the mcrypt php extension is available.
|
252 |
-
*
|
253 |
-
* In order to do the CFB-mode work (fast) phpseclib
|
254 |
-
* use a separate ECB-mode mcrypt resource.
|
255 |
-
*
|
256 |
-
* @link http://phpseclib.sourceforge.net/cfb-demo.phps
|
257 |
-
* @see self::encrypt()
|
258 |
-
* @see self::decrypt()
|
259 |
-
* @see self::_setupMcrypt()
|
260 |
-
* @var resource
|
261 |
-
* @access private
|
262 |
-
*/
|
263 |
-
var $ecb;
|
264 |
-
|
265 |
-
/**
|
266 |
-
* Optimizing value while CFB-encrypting
|
267 |
-
*
|
268 |
-
* Only relevant if $continuousBuffer enabled
|
269 |
-
* and $engine == self::ENGINE_MCRYPT
|
270 |
-
*
|
271 |
-
* It's faster to re-init $enmcrypt if
|
272 |
-
* $buffer bytes > $cfb_init_len than
|
273 |
-
* using the $ecb resource furthermore.
|
274 |
-
*
|
275 |
-
* This value depends of the chosen cipher
|
276 |
-
* and the time it would be needed for it's
|
277 |
-
* initialization [by mcrypt_generic_init()]
|
278 |
-
* which, typically, depends on the complexity
|
279 |
-
* on its internaly Key-expanding algorithm.
|
280 |
-
*
|
281 |
-
* @see self::encrypt()
|
282 |
-
* @var int
|
283 |
-
* @access private
|
284 |
-
*/
|
285 |
-
var $cfb_init_len = 600;
|
286 |
-
|
287 |
-
/**
|
288 |
-
* Does internal cipher state need to be (re)initialized?
|
289 |
-
*
|
290 |
-
* @see self::setKey()
|
291 |
-
* @see self::setIV()
|
292 |
-
* @see self::disableContinuousBuffer()
|
293 |
-
* @var bool
|
294 |
-
* @access private
|
295 |
-
*/
|
296 |
-
var $changed = true;
|
297 |
-
|
298 |
-
/**
|
299 |
-
* Padding status
|
300 |
-
*
|
301 |
-
* @see self::enablePadding()
|
302 |
-
* @var bool
|
303 |
-
* @access private
|
304 |
-
*/
|
305 |
-
var $padding = true;
|
306 |
-
|
307 |
-
/**
|
308 |
-
* Is the mode one that is paddable?
|
309 |
-
*
|
310 |
-
* @see self::__construct()
|
311 |
-
* @var bool
|
312 |
-
* @access private
|
313 |
-
*/
|
314 |
-
var $paddable = false;
|
315 |
-
|
316 |
-
/**
|
317 |
-
* Holds which crypt engine internaly should be use,
|
318 |
-
* which will be determined automatically on __construct()
|
319 |
-
*
|
320 |
-
* Currently available $engines are:
|
321 |
-
* - self::ENGINE_OPENSSL (very fast, php-extension: openssl, extension_loaded('openssl') required)
|
322 |
-
* - self::ENGINE_MCRYPT (fast, php-extension: mcrypt, extension_loaded('mcrypt') required)
|
323 |
-
* - self::ENGINE_INTERNAL (slower, pure php-engine, no php-extension required)
|
324 |
-
*
|
325 |
-
* @see self::_setEngine()
|
326 |
-
* @see self::encrypt()
|
327 |
-
* @see self::decrypt()
|
328 |
-
* @var int
|
329 |
-
* @access private
|
330 |
-
*/
|
331 |
-
var $engine;
|
332 |
-
|
333 |
-
/**
|
334 |
-
* Holds the preferred crypt engine
|
335 |
-
*
|
336 |
-
* @see self::_setEngine()
|
337 |
-
* @see self::setPreferredEngine()
|
338 |
-
* @var int
|
339 |
-
* @access private
|
340 |
-
*/
|
341 |
-
var $preferredEngine;
|
342 |
-
|
343 |
-
/**
|
344 |
-
* The mcrypt specific name of the cipher
|
345 |
-
*
|
346 |
-
* Only used if $engine == self::ENGINE_MCRYPT
|
347 |
-
*
|
348 |
-
* @link http://www.php.net/mcrypt_module_open
|
349 |
-
* @link http://www.php.net/mcrypt_list_algorithms
|
350 |
-
* @see self::_setupMcrypt()
|
351 |
-
* @var string
|
352 |
-
* @access private
|
353 |
-
*/
|
354 |
-
var $cipher_name_mcrypt;
|
355 |
-
|
356 |
-
/**
|
357 |
-
* The openssl specific name of the cipher
|
358 |
-
*
|
359 |
-
* Only used if $engine == self::ENGINE_OPENSSL
|
360 |
-
*
|
361 |
-
* @link http://www.php.net/openssl-get-cipher-methods
|
362 |
-
* @var string
|
363 |
-
* @access private
|
364 |
-
*/
|
365 |
-
var $cipher_name_openssl;
|
366 |
-
|
367 |
-
/**
|
368 |
-
* The openssl specific name of the cipher in ECB mode
|
369 |
-
*
|
370 |
-
* If OpenSSL does not support the mode we're trying to use (CTR)
|
371 |
-
* it can still be emulated with ECB mode.
|
372 |
-
*
|
373 |
-
* @link http://www.php.net/openssl-get-cipher-methods
|
374 |
-
* @var string
|
375 |
-
* @access private
|
376 |
-
*/
|
377 |
-
var $cipher_name_openssl_ecb;
|
378 |
-
|
379 |
-
/**
|
380 |
-
* The default salt used by setPassword()
|
381 |
-
*
|
382 |
-
* @see self::setPassword()
|
383 |
-
* @var string
|
384 |
-
* @access private
|
385 |
-
*/
|
386 |
-
var $password_default_salt = 'phpseclib/salt';
|
387 |
-
|
388 |
-
/**
|
389 |
-
* The name of the performance-optimized callback function
|
390 |
-
*
|
391 |
-
* Used by encrypt() / decrypt()
|
392 |
-
* only if $engine == self::ENGINE_INTERNAL
|
393 |
-
*
|
394 |
-
* @see self::encrypt()
|
395 |
-
* @see self::decrypt()
|
396 |
-
* @see self::_setupInlineCrypt()
|
397 |
-
* @see self::$use_inline_crypt
|
398 |
-
* @var Callback
|
399 |
-
* @access private
|
400 |
-
*/
|
401 |
-
var $inline_crypt;
|
402 |
-
|
403 |
-
/**
|
404 |
-
* Holds whether performance-optimized $inline_crypt() can/should be used.
|
405 |
-
*
|
406 |
-
* @see self::encrypt()
|
407 |
-
* @see self::decrypt()
|
408 |
-
* @see self::inline_crypt
|
409 |
-
* @var mixed
|
410 |
-
* @access private
|
411 |
-
*/
|
412 |
-
var $use_inline_crypt;
|
413 |
-
|
414 |
-
/**
|
415 |
-
* If OpenSSL can be used in ECB but not in CTR we can emulate CTR
|
416 |
-
*
|
417 |
-
* @see self::_openssl_ctr_process()
|
418 |
-
* @var bool
|
419 |
-
* @access private
|
420 |
-
*/
|
421 |
-
var $openssl_emulate_ctr = false;
|
422 |
-
|
423 |
-
/**
|
424 |
-
* Determines what options are passed to openssl_encrypt/decrypt
|
425 |
-
*
|
426 |
-
* @see self::isValidEngine()
|
427 |
-
* @var mixed
|
428 |
-
* @access private
|
429 |
-
*/
|
430 |
-
var $openssl_options;
|
431 |
-
|
432 |
-
/**
|
433 |
-
* Has the key length explicitly been set or should it be derived from the key, itself?
|
434 |
-
*
|
435 |
-
* @see self::setKeyLength()
|
436 |
-
* @var bool
|
437 |
-
* @access private
|
438 |
-
*/
|
439 |
-
var $explicit_key_length = false;
|
440 |
-
|
441 |
-
/**
|
442 |
-
* Don't truncate / null pad key
|
443 |
-
*
|
444 |
-
* @see self::_clearBuffers()
|
445 |
-
* @var bool
|
446 |
-
* @access private
|
447 |
-
*/
|
448 |
-
var $skip_key_adjustment = false;
|
449 |
-
|
450 |
-
/**
|
451 |
-
* Default Constructor.
|
452 |
-
*
|
453 |
-
* Determines whether or not the mcrypt extension should be used.
|
454 |
-
*
|
455 |
-
* $mode could be:
|
456 |
-
*
|
457 |
-
* - self::MODE_ECB
|
458 |
-
*
|
459 |
-
* - self::MODE_CBC
|
460 |
-
*
|
461 |
-
* - self::MODE_CTR
|
462 |
-
*
|
463 |
-
* - self::MODE_CFB
|
464 |
-
*
|
465 |
-
* - self::MODE_OFB
|
466 |
-
*
|
467 |
-
* If not explicitly set, self::MODE_CBC will be used.
|
468 |
-
*
|
469 |
-
* @param int $mode
|
470 |
-
* @access public
|
471 |
-
*/
|
472 |
-
function __construct($mode = self::MODE_CBC)
|
473 |
-
{
|
474 |
-
// $mode dependent settings
|
475 |
-
switch ($mode) {
|
476 |
-
case self::MODE_ECB:
|
477 |
-
$this->paddable = true;
|
478 |
-
$this->mode = self::MODE_ECB;
|
479 |
-
break;
|
480 |
-
case self::MODE_CTR:
|
481 |
-
case self::MODE_CFB:
|
482 |
-
case self::MODE_OFB:
|
483 |
-
case self::MODE_STREAM:
|
484 |
-
$this->mode = $mode;
|
485 |
-
break;
|
486 |
-
case self::MODE_CBC:
|
487 |
-
default:
|
488 |
-
$this->paddable = true;
|
489 |
-
$this->mode = self::MODE_CBC;
|
490 |
-
}
|
491 |
-
|
492 |
-
$this->_setEngine();
|
493 |
-
|
494 |
-
// Determining whether inline crypting can be used by the cipher
|
495 |
-
if ($this->use_inline_crypt !== false) {
|
496 |
-
$this->use_inline_crypt = version_compare(PHP_VERSION, '5.3.0') >= 0 || function_exists('create_function');
|
497 |
-
}
|
498 |
-
}
|
499 |
-
|
500 |
-
/**
|
501 |
-
* Sets the initialization vector. (optional)
|
502 |
-
*
|
503 |
-
* SetIV is not required when self::MODE_ECB (or ie for AES: \phpseclib\Crypt\AES::MODE_ECB) is being used. If not explicitly set, it'll be assumed
|
504 |
-
* to be all zero's.
|
505 |
-
*
|
506 |
-
* @access public
|
507 |
-
* @param string $iv
|
508 |
-
* @internal Can be overwritten by a sub class, but does not have to be
|
509 |
-
*/
|
510 |
-
function setIV($iv)
|
511 |
-
{
|
512 |
-
if ($this->mode == self::MODE_ECB) {
|
513 |
-
return;
|
514 |
-
}
|
515 |
-
|
516 |
-
$this->iv = $iv;
|
517 |
-
$this->changed = true;
|
518 |
-
}
|
519 |
-
|
520 |
-
/**
|
521 |
-
* Sets the key length.
|
522 |
-
*
|
523 |
-
* Keys with explicitly set lengths need to be treated accordingly
|
524 |
-
*
|
525 |
-
* @access public
|
526 |
-
* @param int $length
|
527 |
-
*/
|
528 |
-
function setKeyLength($length)
|
529 |
-
{
|
530 |
-
$this->explicit_key_length = true;
|
531 |
-
$this->changed = true;
|
532 |
-
$this->_setEngine();
|
533 |
-
}
|
534 |
-
|
535 |
-
/**
|
536 |
-
* Returns the current key length in bits
|
537 |
-
*
|
538 |
-
* @access public
|
539 |
-
* @return int
|
540 |
-
*/
|
541 |
-
function getKeyLength()
|
542 |
-
{
|
543 |
-
return $this->key_length << 3;
|
544 |
-
}
|
545 |
-
|
546 |
-
/**
|
547 |
-
* Returns the current block length in bits
|
548 |
-
*
|
549 |
-
* @access public
|
550 |
-
* @return int
|
551 |
-
*/
|
552 |
-
function getBlockLength()
|
553 |
-
{
|
554 |
-
return $this->block_size << 3;
|
555 |
-
}
|
556 |
-
|
557 |
-
/**
|
558 |
-
* Sets the key.
|
559 |
-
*
|
560 |
-
* The min/max length(s) of the key depends on the cipher which is used.
|
561 |
-
* If the key not fits the length(s) of the cipher it will paded with null bytes
|
562 |
-
* up to the closest valid key length. If the key is more than max length,
|
563 |
-
* we trim the excess bits.
|
564 |
-
*
|
565 |
-
* If the key is not explicitly set, it'll be assumed to be all null bytes.
|
566 |
-
*
|
567 |
-
* @access public
|
568 |
-
* @param string $key
|
569 |
-
* @internal Could, but not must, extend by the child Crypt_* class
|
570 |
-
*/
|
571 |
-
function setKey($key)
|
572 |
-
{
|
573 |
-
if (!$this->explicit_key_length) {
|
574 |
-
$this->setKeyLength(strlen($key) << 3);
|
575 |
-
$this->explicit_key_length = false;
|
576 |
-
}
|
577 |
-
|
578 |
-
$this->key = $key;
|
579 |
-
$this->changed = true;
|
580 |
-
$this->_setEngine();
|
581 |
-
}
|
582 |
-
|
583 |
-
/**
|
584 |
-
* Sets the password.
|
585 |
-
*
|
586 |
-
* Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
|
587 |
-
* {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2} or pbkdf1:
|
588 |
-
* $hash, $salt, $count, $dkLen
|
589 |
-
*
|
590 |
-
* Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php
|
591 |
-
*
|
592 |
-
* @see Crypt/Hash.php
|
593 |
-
* @param string $password
|
594 |
-
* @param string $method
|
595 |
-
* @return bool
|
596 |
-
* @access public
|
597 |
-
* @internal Could, but not must, extend by the child Crypt_* class
|
598 |
-
*/
|
599 |
-
function setPassword($password, $method = 'pbkdf2')
|
600 |
-
{
|
601 |
-
$key = '';
|
602 |
-
|
603 |
-
switch ($method) {
|
604 |
-
default: // 'pbkdf2' or 'pbkdf1'
|
605 |
-
$func_args = func_get_args();
|
606 |
-
|
607 |
-
// Hash function
|
608 |
-
$hash = isset($func_args[2]) ? $func_args[2] : 'sha1';
|
609 |
-
|
610 |
-
// WPA and WPA2 use the SSID as the salt
|
611 |
-
$salt = isset($func_args[3]) ? $func_args[3] : $this->password_default_salt;
|
612 |
-
|
613 |
-
// RFC2898#section-4.2 uses 1,000 iterations by default
|
614 |
-
// WPA and WPA2 use 4,096.
|
615 |
-
$count = isset($func_args[4]) ? $func_args[4] : 1000;
|
616 |
-
|
617 |
-
// Keylength
|
618 |
-
if (isset($func_args[5])) {
|
619 |
-
$dkLen = $func_args[5];
|
620 |
-
} else {
|
621 |
-
$dkLen = $method == 'pbkdf1' ? 2 * $this->key_length : $this->key_length;
|
622 |
-
}
|
623 |
-
|
624 |
-
switch (true) {
|
625 |
-
case $method == 'pbkdf1':
|
626 |
-
$hashObj = new Hash();
|
627 |
-
$hashObj->setHash($hash);
|
628 |
-
if ($dkLen > $hashObj->getLength()) {
|
629 |
-
user_error('Derived key too long');
|
630 |
-
return false;
|
631 |
-
}
|
632 |
-
$t = $password . $salt;
|
633 |
-
for ($i = 0; $i < $count; ++$i) {
|
634 |
-
$t = $hashObj->hash($t);
|
635 |
-
}
|
636 |
-
$key = substr($t, 0, $dkLen);
|
637 |
-
|
638 |
-
$this->setKey(substr($key, 0, $dkLen >> 1));
|
639 |
-
$this->setIV(substr($key, $dkLen >> 1));
|
640 |
-
|
641 |
-
return true;
|
642 |
-
// Determining if php[>=5.5.0]'s hash_pbkdf2() function avail- and useable
|
643 |
-
case !function_exists('hash_pbkdf2'):
|
644 |
-
case !function_exists('hash_algos'):
|
645 |
-
case !in_array($hash, hash_algos()):
|
646 |
-
$i = 1;
|
647 |
-
while (strlen($key) < $dkLen) {
|
648 |
-
$hmac = new Hash();
|
649 |
-
$hmac->setHash($hash);
|
650 |
-
$hmac->setKey($password);
|
651 |
-
$f = $u = $hmac->hash($salt . pack('N', $i++));
|
652 |
-
for ($j = 2; $j <= $count; ++$j) {
|
653 |
-
$u = $hmac->hash($u);
|
654 |
-
$f^= $u;
|
655 |
-
}
|
656 |
-
$key.= $f;
|
657 |
-
}
|
658 |
-
$key = substr($key, 0, $dkLen);
|
659 |
-
break;
|
660 |
-
default:
|
661 |
-
$key = hash_pbkdf2($hash, $password, $salt, $count, $dkLen, true);
|
662 |
-
}
|
663 |
-
}
|
664 |
-
|
665 |
-
$this->setKey($key);
|
666 |
-
|
667 |
-
return true;
|
668 |
-
}
|
669 |
-
|
670 |
-
/**
|
671 |
-
* Encrypts a message.
|
672 |
-
*
|
673 |
-
* $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other cipher
|
674 |
-
* implementations may or may not pad in the same manner. Other common approaches to padding and the reasons why it's
|
675 |
-
* necessary are discussed in the following
|
676 |
-
* URL:
|
677 |
-
*
|
678 |
-
* {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
|
679 |
-
*
|
680 |
-
* An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
|
681 |
-
* strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that
|
682 |
-
* length.
|
683 |
-
*
|
684 |
-
* @see self::decrypt()
|
685 |
-
* @access public
|
686 |
-
* @param string $plaintext
|
687 |
-
* @return string $ciphertext
|
688 |
-
* @internal Could, but not must, extend by the child Crypt_* class
|
689 |
-
*/
|
690 |
-
function encrypt($plaintext)
|
691 |
-
{
|
692 |
-
if ($this->paddable) {
|
693 |
-
$plaintext = $this->_pad($plaintext);
|
694 |
-
}
|
695 |
-
|
696 |
-
if ($this->engine === self::ENGINE_OPENSSL) {
|
697 |
-
if ($this->changed) {
|
698 |
-
$this->_clearBuffers();
|
699 |
-
$this->changed = false;
|
700 |
-
}
|
701 |
-
switch ($this->mode) {
|
702 |
-
case self::MODE_STREAM:
|
703 |
-
return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
|
704 |
-
case self::MODE_ECB:
|
705 |
-
$result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
|
706 |
-
return !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result;
|
707 |
-
case self::MODE_CBC:
|
708 |
-
$result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->encryptIV);
|
709 |
-
if (!defined('OPENSSL_RAW_DATA')) {
|
710 |
-
$result = substr($result, 0, -$this->block_size);
|
711 |
-
}
|
712 |
-
if ($this->continuousBuffer) {
|
713 |
-
$this->encryptIV = substr($result, -$this->block_size);
|
714 |
-
}
|
715 |
-
return $result;
|
716 |
-
case self::MODE_CTR:
|
717 |
-
return $this->_openssl_ctr_process($plaintext, $this->encryptIV, $this->enbuffer);
|
718 |
-
case self::MODE_CFB:
|
719 |
-
// cfb loosely routines inspired by openssl's:
|
720 |
-
// {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
|
721 |
-
$ciphertext = '';
|
722 |
-
if ($this->continuousBuffer) {
|
723 |
-
$iv = &$this->encryptIV;
|
724 |
-
$pos = &$this->enbuffer['pos'];
|
725 |
-
} else {
|
726 |
-
$iv = $this->encryptIV;
|
727 |
-
$pos = 0;
|
728 |
-
}
|
729 |
-
$len = strlen($plaintext);
|
730 |
-
$i = 0;
|
731 |
-
if ($pos) {
|
732 |
-
$orig_pos = $pos;
|
733 |
-
$max = $this->block_size - $pos;
|
734 |
-
if ($len >= $max) {
|
735 |
-
$i = $max;
|
736 |
-
$len-= $max;
|
737 |
-
$pos = 0;
|
738 |
-
} else {
|
739 |
-
$i = $len;
|
740 |
-
$pos+= $len;
|
741 |
-
$len = 0;
|
742 |
-
}
|
743 |
-
// ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
|
744 |
-
$ciphertext = substr($iv, $orig_pos) ^ $plaintext;
|
745 |
-
$iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
|
746 |
-
$plaintext = substr($plaintext, $i);
|
747 |
-
}
|
748 |
-
|
749 |
-
$overflow = $len % $this->block_size;
|
750 |
-
|
751 |
-
if ($overflow) {
|
752 |
-
$ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
|
753 |
-
$iv = $this->_string_pop($ciphertext, $this->block_size);
|
754 |
-
|
755 |
-
$size = $len - $overflow;
|
756 |
-
$block = $iv ^ substr($plaintext, -$overflow);
|
757 |
-
$iv = substr_replace($iv, $block, 0, $overflow);
|
758 |
-
$ciphertext.= $block;
|
759 |
-
$pos = $overflow;
|
760 |
-
} elseif ($len) {
|
761 |
-
$ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
|
762 |
-
$iv = substr($ciphertext, -$this->block_size);
|
763 |
-
}
|
764 |
-
|
765 |
-
return $ciphertext;
|
766 |
-
case self::MODE_OFB:
|
767 |
-
return $this->_openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer);
|
768 |
-
}
|
769 |
-
}
|
770 |
-
|
771 |
-
if ($this->engine === self::ENGINE_MCRYPT) {
|
772 |
-
if ($this->changed) {
|
773 |
-
$this->_setupMcrypt();
|
774 |
-
$this->changed = false;
|
775 |
-
}
|
776 |
-
if ($this->enchanged) {
|
777 |
-
@mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
|
778 |
-
$this->enchanged = false;
|
779 |
-
}
|
780 |
-
|
781 |
-
// re: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
|
782 |
-
// using mcrypt's default handing of CFB the above would output two different things. using phpseclib's
|
783 |
-
// rewritten CFB implementation the above outputs the same thing twice.
|
784 |
-
if ($this->mode == self::MODE_CFB && $this->continuousBuffer) {
|
785 |
-
$block_size = $this->block_size;
|
786 |
-
$iv = &$this->encryptIV;
|
787 |
-
$pos = &$this->enbuffer['pos'];
|
788 |
-
$len = strlen($plaintext);
|
789 |
-
$ciphertext = '';
|
790 |
-
$i = 0;
|
791 |
-
if ($pos) {
|
792 |
-
$orig_pos = $pos;
|
793 |
-
$max = $block_size - $pos;
|
794 |
-
if ($len >= $max) {
|
795 |
-
$i = $max;
|
796 |
-
$len-= $max;
|
797 |
-
$pos = 0;
|
798 |
-
} else {
|
799 |
-
$i = $len;
|
800 |
-
$pos+= $len;
|
801 |
-
$len = 0;
|
802 |
-
}
|
803 |
-
$ciphertext = substr($iv, $orig_pos) ^ $plaintext;
|
804 |
-
$iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
|
805 |
-
$this->enbuffer['enmcrypt_init'] = true;
|
806 |
-
}
|
807 |
-
if ($len >= $block_size) {
|
808 |
-
if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) {
|
809 |
-
if ($this->enbuffer['enmcrypt_init'] === true) {
|
810 |
-
@mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
|
811 |
-
$this->enbuffer['enmcrypt_init'] = false;
|
812 |
-
}
|
813 |
-
$ciphertext.= @mcrypt_generic($this->enmcrypt, substr($plaintext, $i, $len - $len % $block_size));
|
814 |
-
$iv = substr($ciphertext, -$block_size);
|
815 |
-
$len%= $block_size;
|
816 |
-
} else {
|
817 |
-
while ($len >= $block_size) {
|
818 |
-
$iv = @mcrypt_generic($this->ecb, $iv) ^ substr($plaintext, $i, $block_size);
|
819 |
-
$ciphertext.= $iv;
|
820 |
-
$len-= $block_size;
|
821 |
-
$i+= $block_size;
|
822 |
-
}
|
823 |
-
}
|
824 |
-
}
|
825 |
-
|
826 |
-
if ($len) {
|
827 |
-
$iv = @mcrypt_generic($this->ecb, $iv);
|
828 |
-
$block = $iv ^ substr($plaintext, -$len);
|
829 |
-
$iv = substr_replace($iv, $block, 0, $len);
|
830 |
-
$ciphertext.= $block;
|
831 |
-
$pos = $len;
|
832 |
-
}
|
833 |
-
|
834 |
-
return $ciphertext;
|
835 |
-
}
|
836 |
-
|
837 |
-
$ciphertext = @mcrypt_generic($this->enmcrypt, $plaintext);
|
838 |
-
|
839 |
-
if (!$this->continuousBuffer) {
|
840 |
-
@mcrypt_generic_init($this->enmcrypt, $this->key, $this->encryptIV);
|
841 |
-
}
|
842 |
-
|
843 |
-
return $ciphertext;
|
844 |
-
}
|
845 |
-
|
846 |
-
if ($this->changed) {
|
847 |
-
$this->_setup();
|
848 |
-
$this->changed = false;
|
849 |
-
}
|
850 |
-
if ($this->use_inline_crypt) {
|
851 |
-
$inline = $this->inline_crypt;
|
852 |
-
return $inline('encrypt', $this, $plaintext);
|
853 |
-
}
|
854 |
-
|
855 |
-
$buffer = &$this->enbuffer;
|
856 |
-
$block_size = $this->block_size;
|
857 |
-
$ciphertext = '';
|
858 |
-
switch ($this->mode) {
|
859 |
-
case self::MODE_ECB:
|
860 |
-
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
|
861 |
-
$ciphertext.= $this->_encryptBlock(substr($plaintext, $i, $block_size));
|
862 |
-
}
|
863 |
-
break;
|
864 |
-
case self::MODE_CBC:
|
865 |
-
$xor = $this->encryptIV;
|
866 |
-
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
|
867 |
-
$block = substr($plaintext, $i, $block_size);
|
868 |
-
$block = $this->_encryptBlock($block ^ $xor);
|
869 |
-
$xor = $block;
|
870 |
-
$ciphertext.= $block;
|
871 |
-
}
|
872 |
-
if ($this->continuousBuffer) {
|
873 |
-
$this->encryptIV = $xor;
|
874 |
-
}
|
875 |
-
break;
|
876 |
-
case self::MODE_CTR:
|
877 |
-
$xor = $this->encryptIV;
|
878 |
-
if (strlen($buffer['ciphertext'])) {
|
879 |
-
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
|
880 |
-
$block = substr($plaintext, $i, $block_size);
|
881 |
-
if (strlen($block) > strlen($buffer['ciphertext'])) {
|
882 |
-
$buffer['ciphertext'].= $this->_encryptBlock($xor);
|
883 |
-
}
|
884 |
-
$this->_increment_str($xor);
|
885 |
-
$key = $this->_string_shift($buffer['ciphertext'], $block_size);
|
886 |
-
$ciphertext.= $block ^ $key;
|
887 |
-
}
|
888 |
-
} else {
|
889 |
-
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
|
890 |
-
$block = substr($plaintext, $i, $block_size);
|
891 |
-
$key = $this->_encryptBlock($xor);
|
892 |
-
$this->_increment_str($xor);
|
893 |
-
$ciphertext.= $block ^ $key;
|
894 |
-
}
|
895 |
-
}
|
896 |
-
if ($this->continuousBuffer) {
|
897 |
-
$this->encryptIV = $xor;
|
898 |
-
if ($start = strlen($plaintext) % $block_size) {
|
899 |
-
$buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
|
900 |
-
}
|
901 |
-
}
|
902 |
-
break;
|
903 |
-
case self::MODE_CFB:
|
904 |
-
// cfb loosely routines inspired by openssl's:
|
905 |
-
// {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
|
906 |
-
if ($this->continuousBuffer) {
|
907 |
-
$iv = &$this->encryptIV;
|
908 |
-
$pos = &$buffer['pos'];
|
909 |
-
} else {
|
910 |
-
$iv = $this->encryptIV;
|
911 |
-
$pos = 0;
|
912 |
-
}
|
913 |
-
$len = strlen($plaintext);
|
914 |
-
$i = 0;
|
915 |
-
if ($pos) {
|
916 |
-
$orig_pos = $pos;
|
917 |
-
$max = $block_size - $pos;
|
918 |
-
if ($len >= $max) {
|
919 |
-
$i = $max;
|
920 |
-
$len-= $max;
|
921 |
-
$pos = 0;
|
922 |
-
} else {
|
923 |
-
$i = $len;
|
924 |
-
$pos+= $len;
|
925 |
-
$len = 0;
|
926 |
-
}
|
927 |
-
// ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
|
928 |
-
$ciphertext = substr($iv, $orig_pos) ^ $plaintext;
|
929 |
-
$iv = substr_replace($iv, $ciphertext, $orig_pos, $i);
|
930 |
-
}
|
931 |
-
while ($len >= $block_size) {
|
932 |
-
$iv = $this->_encryptBlock($iv) ^ substr($plaintext, $i, $block_size);
|
933 |
-
$ciphertext.= $iv;
|
934 |
-
$len-= $block_size;
|
935 |
-
$i+= $block_size;
|
936 |
-
}
|
937 |
-
if ($len) {
|
938 |
-
$iv = $this->_encryptBlock($iv);
|
939 |
-
$block = $iv ^ substr($plaintext, $i);
|
940 |
-
$iv = substr_replace($iv, $block, 0, $len);
|
941 |
-
$ciphertext.= $block;
|
942 |
-
$pos = $len;
|
943 |
-
}
|
944 |
-
break;
|
945 |
-
case self::MODE_OFB:
|
946 |
-
$xor = $this->encryptIV;
|
947 |
-
if (strlen($buffer['xor'])) {
|
948 |
-
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
|
949 |
-
$block = substr($plaintext, $i, $block_size);
|
950 |
-
if (strlen($block) > strlen($buffer['xor'])) {
|
951 |
-
$xor = $this->_encryptBlock($xor);
|
952 |
-
$buffer['xor'].= $xor;
|
953 |
-
}
|
954 |
-
$key = $this->_string_shift($buffer['xor'], $block_size);
|
955 |
-
$ciphertext.= $block ^ $key;
|
956 |
-
}
|
957 |
-
} else {
|
958 |
-
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
|
959 |
-
$xor = $this->_encryptBlock($xor);
|
960 |
-
$ciphertext.= substr($plaintext, $i, $block_size) ^ $xor;
|
961 |
-
}
|
962 |
-
$key = $xor;
|
963 |
-
}
|
964 |
-
if ($this->continuousBuffer) {
|
965 |
-
$this->encryptIV = $xor;
|
966 |
-
if ($start = strlen($plaintext) % $block_size) {
|
967 |
-
$buffer['xor'] = substr($key, $start) . $buffer['xor'];
|
968 |
-
}
|
969 |
-
}
|
970 |
-
break;
|
971 |
-
case self::MODE_STREAM:
|
972 |
-
$ciphertext = $this->_encryptBlock($plaintext);
|
973 |
-
break;
|
974 |
-
}
|
975 |
-
|
976 |
-
return $ciphertext;
|
977 |
-
}
|
978 |
-
|
979 |
-
/**
|
980 |
-
* Decrypts a message.
|
981 |
-
*
|
982 |
-
* If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until
|
983 |
-
* it is.
|
984 |
-
*
|
985 |
-
* @see self::encrypt()
|
986 |
-
* @access public
|
987 |
-
* @param string $ciphertext
|
988 |
-
* @return string $plaintext
|
989 |
-
* @internal Could, but not must, extend by the child Crypt_* class
|
990 |
-
*/
|
991 |
-
function decrypt($ciphertext)
|
992 |
-
{
|
993 |
-
if ($this->paddable) {
|
994 |
-
// we pad with chr(0) since that's what mcrypt_generic does. to quote from {@link http://www.php.net/function.mcrypt-generic}:
|
995 |
-
// "The data is padded with "\0" to make sure the length of the data is n * blocksize."
|
996 |
-
$ciphertext = str_pad($ciphertext, strlen($ciphertext) + ($this->block_size - strlen($ciphertext) % $this->block_size) % $this->block_size, chr(0));
|
997 |
-
}
|
998 |
-
|
999 |
-
if ($this->engine === self::ENGINE_OPENSSL) {
|
1000 |
-
if ($this->changed) {
|
1001 |
-
$this->_clearBuffers();
|
1002 |
-
$this->changed = false;
|
1003 |
-
}
|
1004 |
-
switch ($this->mode) {
|
1005 |
-
case self::MODE_STREAM:
|
1006 |
-
$plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
|
1007 |
-
break;
|
1008 |
-
case self::MODE_ECB:
|
1009 |
-
if (!defined('OPENSSL_RAW_DATA')) {
|
1010 |
-
$ciphertext.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $this->key, true);
|
1011 |
-
}
|
1012 |
-
$plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options);
|
1013 |
-
break;
|
1014 |
-
case self::MODE_CBC:
|
1015 |
-
if (!defined('OPENSSL_RAW_DATA')) {
|
1016 |
-
$padding = str_repeat(chr($this->block_size), $this->block_size) ^ substr($ciphertext, -$this->block_size);
|
1017 |
-
$ciphertext.= substr(openssl_encrypt($padding, $this->cipher_name_openssl_ecb, $this->key, true), 0, $this->block_size);
|
1018 |
-
$offset = 2 * $this->block_size;
|
1019 |
-
} else {
|
1020 |
-
$offset = $this->block_size;
|
1021 |
-
}
|
1022 |
-
$plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $this->decryptIV);
|
1023 |
-
if ($this->continuousBuffer) {
|
1024 |
-
$this->decryptIV = substr($ciphertext, -$offset, $this->block_size);
|
1025 |
-
}
|
1026 |
-
break;
|
1027 |
-
case self::MODE_CTR:
|
1028 |
-
$plaintext = $this->_openssl_ctr_process($ciphertext, $this->decryptIV, $this->debuffer);
|
1029 |
-
break;
|
1030 |
-
case self::MODE_CFB:
|
1031 |
-
// cfb loosely routines inspired by openssl's:
|
1032 |
-
// {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
|
1033 |
-
$plaintext = '';
|
1034 |
-
if ($this->continuousBuffer) {
|
1035 |
-
$iv = &$this->decryptIV;
|
1036 |
-
$pos = &$this->buffer['pos'];
|
1037 |
-
} else {
|
1038 |
-
$iv = $this->decryptIV;
|
1039 |
-
$pos = 0;
|
1040 |
-
}
|
1041 |
-
$len = strlen($ciphertext);
|
1042 |
-
$i = 0;
|
1043 |
-
if ($pos) {
|
1044 |
-
$orig_pos = $pos;
|
1045 |
-
$max = $this->block_size - $pos;
|
1046 |
-
if ($len >= $max) {
|
1047 |
-
$i = $max;
|
1048 |
-
$len-= $max;
|
1049 |
-
$pos = 0;
|
1050 |
-
} else {
|
1051 |
-
$i = $len;
|
1052 |
-
$pos+= $len;
|
1053 |
-
$len = 0;
|
1054 |
-
}
|
1055 |
-
// ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $this->blocksize
|
1056 |
-
$plaintext = substr($iv, $orig_pos) ^ $ciphertext;
|
1057 |
-
$iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
|
1058 |
-
$ciphertext = substr($ciphertext, $i);
|
1059 |
-
}
|
1060 |
-
$overflow = $len % $this->block_size;
|
1061 |
-
if ($overflow) {
|
1062 |
-
$plaintext.= openssl_decrypt(substr($ciphertext, 0, -$overflow), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
|
1063 |
-
if ($len - $overflow) {
|
1064 |
-
$iv = substr($ciphertext, -$overflow - $this->block_size, -$overflow);
|
1065 |
-
}
|
1066 |
-
$iv = openssl_encrypt(str_repeat("\0", $this->block_size), $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
|
1067 |
-
$plaintext.= $iv ^ substr($ciphertext, -$overflow);
|
1068 |
-
$iv = substr_replace($iv, substr($ciphertext, -$overflow), 0, $overflow);
|
1069 |
-
$pos = $overflow;
|
1070 |
-
} elseif ($len) {
|
1071 |
-
$plaintext.= openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, $this->openssl_options, $iv);
|
1072 |
-
$iv = substr($ciphertext, -$this->block_size);
|
1073 |
-
}
|
1074 |
-
break;
|
1075 |
-
case self::MODE_OFB:
|
1076 |
-
$plaintext = $this->_openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer);
|
1077 |
-
}
|
1078 |
-
|
1079 |
-
return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
|
1080 |
-
}
|
1081 |
-
|
1082 |
-
if ($this->engine === self::ENGINE_MCRYPT) {
|
1083 |
-
$block_size = $this->block_size;
|
1084 |
-
if ($this->changed) {
|
1085 |
-
$this->_setupMcrypt();
|
1086 |
-
$this->changed = false;
|
1087 |
-
}
|
1088 |
-
if ($this->dechanged) {
|
1089 |
-
@mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
|
1090 |
-
$this->dechanged = false;
|
1091 |
-
}
|
1092 |
-
|
1093 |
-
if ($this->mode == self::MODE_CFB && $this->continuousBuffer) {
|
1094 |
-
$iv = &$this->decryptIV;
|
1095 |
-
$pos = &$this->debuffer['pos'];
|
1096 |
-
$len = strlen($ciphertext);
|
1097 |
-
$plaintext = '';
|
1098 |
-
$i = 0;
|
1099 |
-
if ($pos) {
|
1100 |
-
$orig_pos = $pos;
|
1101 |
-
$max = $block_size - $pos;
|
1102 |
-
if ($len >= $max) {
|
1103 |
-
$i = $max;
|
1104 |
-
$len-= $max;
|
1105 |
-
$pos = 0;
|
1106 |
-
} else {
|
1107 |
-
$i = $len;
|
1108 |
-
$pos+= $len;
|
1109 |
-
$len = 0;
|
1110 |
-
}
|
1111 |
-
// ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
|
1112 |
-
$plaintext = substr($iv, $orig_pos) ^ $ciphertext;
|
1113 |
-
$iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
|
1114 |
-
}
|
1115 |
-
if ($len >= $block_size) {
|
1116 |
-
$cb = substr($ciphertext, $i, $len - $len % $block_size);
|
1117 |
-
$plaintext.= @mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
|
1118 |
-
$iv = substr($cb, -$block_size);
|
1119 |
-
$len%= $block_size;
|
1120 |
-
}
|
1121 |
-
if ($len) {
|
1122 |
-
$iv = @mcrypt_generic($this->ecb, $iv);
|
1123 |
-
$plaintext.= $iv ^ substr($ciphertext, -$len);
|
1124 |
-
$iv = substr_replace($iv, substr($ciphertext, -$len), 0, $len);
|
1125 |
-
$pos = $len;
|
1126 |
-
}
|
1127 |
-
|
1128 |
-
return $plaintext;
|
1129 |
-
}
|
1130 |
-
|
1131 |
-
$plaintext = @mdecrypt_generic($this->demcrypt, $ciphertext);
|
1132 |
-
|
1133 |
-
if (!$this->continuousBuffer) {
|
1134 |
-
@mcrypt_generic_init($this->demcrypt, $this->key, $this->decryptIV);
|
1135 |
-
}
|
1136 |
-
|
1137 |
-
return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
|
1138 |
-
}
|
1139 |
-
|
1140 |
-
if ($this->changed) {
|
1141 |
-
$this->_setup();
|
1142 |
-
$this->changed = false;
|
1143 |
-
}
|
1144 |
-
if ($this->use_inline_crypt) {
|
1145 |
-
$inline = $this->inline_crypt;
|
1146 |
-
return $inline('decrypt', $this, $ciphertext);
|
1147 |
-
}
|
1148 |
-
|
1149 |
-
$block_size = $this->block_size;
|
1150 |
-
|
1151 |
-
$buffer = &$this->debuffer;
|
1152 |
-
$plaintext = '';
|
1153 |
-
switch ($this->mode) {
|
1154 |
-
case self::MODE_ECB:
|
1155 |
-
for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
|
1156 |
-
$plaintext.= $this->_decryptBlock(substr($ciphertext, $i, $block_size));
|
1157 |
-
}
|
1158 |
-
break;
|
1159 |
-
case self::MODE_CBC:
|
1160 |
-
$xor = $this->decryptIV;
|
1161 |
-
for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
|
1162 |
-
$block = substr($ciphertext, $i, $block_size);
|
1163 |
-
$plaintext.= $this->_decryptBlock($block) ^ $xor;
|
1164 |
-
$xor = $block;
|
1165 |
-
}
|
1166 |
-
if ($this->continuousBuffer) {
|
1167 |
-
$this->decryptIV = $xor;
|
1168 |
-
}
|
1169 |
-
break;
|
1170 |
-
case self::MODE_CTR:
|
1171 |
-
$xor = $this->decryptIV;
|
1172 |
-
if (strlen($buffer['ciphertext'])) {
|
1173 |
-
for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
|
1174 |
-
$block = substr($ciphertext, $i, $block_size);
|
1175 |
-
if (strlen($block) > strlen($buffer['ciphertext'])) {
|
1176 |
-
$buffer['ciphertext'].= $this->_encryptBlock($xor);
|
1177 |
-
$this->_increment_str($xor);
|
1178 |
-
}
|
1179 |
-
$key = $this->_string_shift($buffer['ciphertext'], $block_size);
|
1180 |
-
$plaintext.= $block ^ $key;
|
1181 |
-
}
|
1182 |
-
} else {
|
1183 |
-
for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
|
1184 |
-
$block = substr($ciphertext, $i, $block_size);
|
1185 |
-
$key = $this->_encryptBlock($xor);
|
1186 |
-
$this->_increment_str($xor);
|
1187 |
-
$plaintext.= $block ^ $key;
|
1188 |
-
}
|
1189 |
-
}
|
1190 |
-
if ($this->continuousBuffer) {
|
1191 |
-
$this->decryptIV = $xor;
|
1192 |
-
if ($start = strlen($ciphertext) % $block_size) {
|
1193 |
-
$buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
|
1194 |
-
}
|
1195 |
-
}
|
1196 |
-
break;
|
1197 |
-
case self::MODE_CFB:
|
1198 |
-
if ($this->continuousBuffer) {
|
1199 |
-
$iv = &$this->decryptIV;
|
1200 |
-
$pos = &$buffer['pos'];
|
1201 |
-
} else {
|
1202 |
-
$iv = $this->decryptIV;
|
1203 |
-
$pos = 0;
|
1204 |
-
}
|
1205 |
-
$len = strlen($ciphertext);
|
1206 |
-
$i = 0;
|
1207 |
-
if ($pos) {
|
1208 |
-
$orig_pos = $pos;
|
1209 |
-
$max = $block_size - $pos;
|
1210 |
-
if ($len >= $max) {
|
1211 |
-
$i = $max;
|
1212 |
-
$len-= $max;
|
1213 |
-
$pos = 0;
|
1214 |
-
} else {
|
1215 |
-
$i = $len;
|
1216 |
-
$pos+= $len;
|
1217 |
-
$len = 0;
|
1218 |
-
}
|
1219 |
-
// ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
|
1220 |
-
$plaintext = substr($iv, $orig_pos) ^ $ciphertext;
|
1221 |
-
$iv = substr_replace($iv, substr($ciphertext, 0, $i), $orig_pos, $i);
|
1222 |
-
}
|
1223 |
-
while ($len >= $block_size) {
|
1224 |
-
$iv = $this->_encryptBlock($iv);
|
1225 |
-
$cb = substr($ciphertext, $i, $block_size);
|
1226 |
-
$plaintext.= $iv ^ $cb;
|
1227 |
-
$iv = $cb;
|
1228 |
-
$len-= $block_size;
|
1229 |
-
$i+= $block_size;
|
1230 |
-
}
|
1231 |
-
if ($len) {
|
1232 |
-
$iv = $this->_encryptBlock($iv);
|
1233 |
-
$plaintext.= $iv ^ substr($ciphertext, $i);
|
1234 |
-
$iv = substr_replace($iv, substr($ciphertext, $i), 0, $len);
|
1235 |
-
$pos = $len;
|
1236 |
-
}
|
1237 |
-
break;
|
1238 |
-
case self::MODE_OFB:
|
1239 |
-
$xor = $this->decryptIV;
|
1240 |
-
if (strlen($buffer['xor'])) {
|
1241 |
-
for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
|
1242 |
-
$block = substr($ciphertext, $i, $block_size);
|
1243 |
-
if (strlen($block) > strlen($buffer['xor'])) {
|
1244 |
-
$xor = $this->_encryptBlock($xor);
|
1245 |
-
$buffer['xor'].= $xor;
|
1246 |
-
}
|
1247 |
-
$key = $this->_string_shift($buffer['xor'], $block_size);
|
1248 |
-
$plaintext.= $block ^ $key;
|
1249 |
-
}
|
1250 |
-
} else {
|
1251 |
-
for ($i = 0; $i < strlen($ciphertext); $i+=$block_size) {
|
1252 |
-
$xor = $this->_encryptBlock($xor);
|
1253 |
-
$plaintext.= substr($ciphertext, $i, $block_size) ^ $xor;
|
1254 |
-
}
|
1255 |
-
$key = $xor;
|
1256 |
-
}
|
1257 |
-
if ($this->continuousBuffer) {
|
1258 |
-
$this->decryptIV = $xor;
|
1259 |
-
if ($start = strlen($ciphertext) % $block_size) {
|
1260 |
-
$buffer['xor'] = substr($key, $start) . $buffer['xor'];
|
1261 |
-
}
|
1262 |
-
}
|
1263 |
-
break;
|
1264 |
-
case self::MODE_STREAM:
|
1265 |
-
$plaintext = $this->_decryptBlock($ciphertext);
|
1266 |
-
break;
|
1267 |
-
}
|
1268 |
-
return $this->paddable ? $this->_unpad($plaintext) : $plaintext;
|
1269 |
-
}
|
1270 |
-
|
1271 |
-
/**
|
1272 |
-
* OpenSSL CTR Processor
|
1273 |
-
*
|
1274 |
-
* PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
|
1275 |
-
* for CTR is the same for both encrypting and decrypting this function is re-used by both Base::encrypt()
|
1276 |
-
* and Base::decrypt(). Also, OpenSSL doesn't implement CTR for all of it's symmetric ciphers so this
|
1277 |
-
* function will emulate CTR with ECB when necessary.
|
1278 |
-
*
|
1279 |
-
* @see self::encrypt()
|
1280 |
-
* @see self::decrypt()
|
1281 |
-
* @param string $plaintext
|
1282 |
-
* @param string $encryptIV
|
1283 |
-
* @param array $buffer
|
1284 |
-
* @return string
|
1285 |
-
* @access private
|
1286 |
-
*/
|
1287 |
-
function _openssl_ctr_process($plaintext, &$encryptIV, &$buffer)
|
1288 |
-
{
|
1289 |
-
$ciphertext = '';
|
1290 |
-
|
1291 |
-
$block_size = $this->block_size;
|
1292 |
-
$key = $this->key;
|
1293 |
-
|
1294 |
-
if ($this->openssl_emulate_ctr) {
|
1295 |
-
$xor = $encryptIV;
|
1296 |
-
if (strlen($buffer['ciphertext'])) {
|
1297 |
-
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
|
1298 |
-
$block = substr($plaintext, $i, $block_size);
|
1299 |
-
if (strlen($block) > strlen($buffer['ciphertext'])) {
|
1300 |
-
$result = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
|
1301 |
-
$result = !defined('OPENSSL_RAW_DATA') ? substr($result, 0, -$this->block_size) : $result;
|
1302 |
-
$buffer['ciphertext'].= $result;
|
1303 |
-
}
|
1304 |
-
$this->_increment_str($xor);
|
1305 |
-
$otp = $this->_string_shift($buffer['ciphertext'], $block_size);
|
1306 |
-
$ciphertext.= $block ^ $otp;
|
1307 |
-
}
|
1308 |
-
} else {
|
1309 |
-
for ($i = 0; $i < strlen($plaintext); $i+=$block_size) {
|
1310 |
-
$block = substr($plaintext, $i, $block_size);
|
1311 |
-
$otp = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
|
1312 |
-
$otp = !defined('OPENSSL_RAW_DATA') ? substr($otp, 0, -$this->block_size) : $otp;
|
1313 |
-
$this->_increment_str($xor);
|
1314 |
-
$ciphertext.= $block ^ $otp;
|
1315 |
-
}
|
1316 |
-
}
|
1317 |
-
if ($this->continuousBuffer) {
|
1318 |
-
$encryptIV = $xor;
|
1319 |
-
if ($start = strlen($plaintext) % $block_size) {
|
1320 |
-
$buffer['ciphertext'] = substr($key, $start) . $buffer['ciphertext'];
|
1321 |
-
}
|
1322 |
-
}
|
1323 |
-
|
1324 |
-
return $ciphertext;
|
1325 |
-
}
|
1326 |
-
|
1327 |
-
if (strlen($buffer['ciphertext'])) {
|
1328 |
-
$ciphertext = $plaintext ^ $this->_string_shift($buffer['ciphertext'], strlen($plaintext));
|
1329 |
-
$plaintext = substr($plaintext, strlen($ciphertext));
|
1330 |
-
|
1331 |
-
if (!strlen($plaintext)) {
|
1332 |
-
return $ciphertext;
|
1333 |
-
}
|
1334 |
-
}
|
1335 |
-
|
1336 |
-
$overflow = strlen($plaintext) % $block_size;
|
1337 |
-
if ($overflow) {
|
1338 |
-
$plaintext2 = $this->_string_pop($plaintext, $overflow); // ie. trim $plaintext to a multiple of $block_size and put rest of $plaintext in $plaintext2
|
1339 |
-
$encrypted = openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
|
1340 |
-
$temp = $this->_string_pop($encrypted, $block_size);
|
1341 |
-
$ciphertext.= $encrypted . ($plaintext2 ^ $temp);
|
1342 |
-
if ($this->continuousBuffer) {
|
1343 |
-
$buffer['ciphertext'] = substr($temp, $overflow);
|
1344 |
-
$encryptIV = $temp;
|
1345 |
-
}
|
1346 |
-
} elseif (!strlen($buffer['ciphertext'])) {
|
1347 |
-
$ciphertext.= openssl_encrypt($plaintext . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
|
1348 |
-
$temp = $this->_string_pop($ciphertext, $block_size);
|
1349 |
-
if ($this->continuousBuffer) {
|
1350 |
-
$encryptIV = $temp;
|
1351 |
-
}
|
1352 |
-
}
|
1353 |
-
if ($this->continuousBuffer) {
|
1354 |
-
if (!defined('OPENSSL_RAW_DATA')) {
|
1355 |
-
$encryptIV.= openssl_encrypt('', $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
|
1356 |
-
}
|
1357 |
-
$encryptIV = openssl_decrypt($encryptIV, $this->cipher_name_openssl_ecb, $key, $this->openssl_options);
|
1358 |
-
if ($overflow) {
|
1359 |
-
$this->_increment_str($encryptIV);
|
1360 |
-
}
|
1361 |
-
}
|
1362 |
-
|
1363 |
-
return $ciphertext;
|
1364 |
-
}
|
1365 |
-
|
1366 |
-
/**
|
1367 |
-
* OpenSSL OFB Processor
|
1368 |
-
*
|
1369 |
-
* PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
|
1370 |
-
* for OFB is the same for both encrypting and decrypting this function is re-used by both Base::encrypt()
|
1371 |
-
* and Base::decrypt().
|
1372 |
-
*
|
1373 |
-
* @see self::encrypt()
|
1374 |
-
* @see self::decrypt()
|
1375 |
-
* @param string $plaintext
|
1376 |
-
* @param string $encryptIV
|
1377 |
-
* @param array $buffer
|
1378 |
-
* @return string
|
1379 |
-
* @access private
|
1380 |
-
*/
|
1381 |
-
function _openssl_ofb_process($plaintext, &$encryptIV, &$buffer)
|
1382 |
-
{
|
1383 |
-
if (strlen($buffer['xor'])) {
|
1384 |
-
$ciphertext = $plaintext ^ $buffer['xor'];
|
1385 |
-
$buffer['xor'] = substr($buffer['xor'], strlen($ciphertext));
|
1386 |
-
$plaintext = substr($plaintext, strlen($ciphertext));
|
1387 |
-
} else {
|
1388 |
-
$ciphertext = '';
|
1389 |
-
}
|
1390 |
-
|
1391 |
-
$block_size = $this->block_size;
|
1392 |
-
|
1393 |
-
$len = strlen($plaintext);
|
1394 |
-
$key = $this->key;
|
1395 |
-
$overflow = $len % $block_size;
|
1396 |
-
|
1397 |
-
if (strlen($plaintext)) {
|
1398 |
-
if ($overflow) {
|
1399 |
-
$ciphertext.= openssl_encrypt(substr($plaintext, 0, -$overflow) . str_repeat("\0", $block_size), $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
|
1400 |
-
$xor = $this->_string_pop($ciphertext, $block_size);
|
1401 |
-
if ($this->continuousBuffer) {
|
1402 |
-
$encryptIV = $xor;
|
1403 |
-
}
|
1404 |
-
$ciphertext.= $this->_string_shift($xor, $overflow) ^ substr($plaintext, -$overflow);
|
1405 |
-
if ($this->continuousBuffer) {
|
1406 |
-
$buffer['xor'] = $xor;
|
1407 |
-
}
|
1408 |
-
} else {
|
1409 |
-
$ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $key, $this->openssl_options, $encryptIV);
|
1410 |
-
if ($this->continuousBuffer) {
|
1411 |
-
$encryptIV = substr($ciphertext, -$block_size) ^ substr($plaintext, -$block_size);
|
1412 |
-
}
|
1413 |
-
}
|
1414 |
-
}
|
1415 |
-
|
1416 |
-
return $ciphertext;
|
1417 |
-
}
|
1418 |
-
|
1419 |
-
/**
|
1420 |
-
* phpseclib <-> OpenSSL Mode Mapper
|
1421 |
-
*
|
1422 |
-
* May need to be overwritten by classes extending this one in some cases
|
1423 |
-
*
|
1424 |
-
* @return int
|
1425 |
-
* @access private
|
1426 |
-
*/
|
1427 |
-
function _openssl_translate_mode()
|
1428 |
-
{
|
1429 |
-
switch ($this->mode) {
|
1430 |
-
case self::MODE_ECB:
|
1431 |
-
return 'ecb';
|
1432 |
-
case self::MODE_CBC:
|
1433 |
-
return 'cbc';
|
1434 |
-
case self::MODE_CTR:
|
1435 |
-
return 'ctr';
|
1436 |
-
case self::MODE_CFB:
|
1437 |
-
return 'cfb';
|
1438 |
-
case self::MODE_OFB:
|
1439 |
-
return 'ofb';
|
1440 |
-
}
|
1441 |
-
}
|
1442 |
-
|
1443 |
-
/**
|
1444 |
-
* Pad "packets".
|
1445 |
-
*
|
1446 |
-
* Block ciphers working by encrypting between their specified [$this->]block_size at a time
|
1447 |
-
* If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to
|
1448 |
-
* pad the input so that it is of the proper length.
|
1449 |
-
*
|
1450 |
-
* Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH,
|
1451 |
-
* where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
|
1452 |
-
* away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
|
1453 |
-
* transmitted separately)
|
1454 |
-
*
|
1455 |
-
* @see self::disablePadding()
|
1456 |
-
* @access public
|
1457 |
-
*/
|
1458 |
-
function enablePadding()
|
1459 |
-
{
|
1460 |
-
$this->padding = true;
|
1461 |
-
}
|
1462 |
-
|
1463 |
-
/**
|
1464 |
-
* Do not pad packets.
|
1465 |
-
*
|
1466 |
-
* @see self::enablePadding()
|
1467 |
-
* @access public
|
1468 |
-
*/
|
1469 |
-
function disablePadding()
|
1470 |
-
{
|
1471 |
-
$this->padding = false;
|
1472 |
-
}
|
1473 |
-
|
1474 |
-
/**
|
1475 |
-
* Treat consecutive "packets" as if they are a continuous buffer.
|
1476 |
-
*
|
1477 |
-
* Say you have a 32-byte plaintext $plaintext. Using the default behavior, the two following code snippets
|
1478 |
-
* will yield different outputs:
|
1479 |
-
*
|
1480 |
-
* <code>
|
1481 |
-
* echo $rijndael->encrypt(substr($plaintext, 0, 16));
|
1482 |
-
* echo $rijndael->encrypt(substr($plaintext, 16, 16));
|
1483 |
-
* </code>
|
1484 |
-
* <code>
|
1485 |
-
* echo $rijndael->encrypt($plaintext);
|
1486 |
-
* </code>
|
1487 |
-
*
|
1488 |
-
* The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
|
1489 |
-
* another, as demonstrated with the following:
|
1490 |
-
*
|
1491 |
-
* <code>
|
1492 |
-
* $rijndael->encrypt(substr($plaintext, 0, 16));
|
1493 |
-
* echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
|
1494 |
-
* </code>
|
1495 |
-
* <code>
|
1496 |
-
* echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
|
1497 |
-
* </code>
|
1498 |
-
*
|
1499 |
-
* With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
|
1500 |
-
* outputs. The reason is due to the fact that the initialization vector's change after every encryption /
|
1501 |
-
* decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
|
1502 |
-
*
|
1503 |
-
* Put another way, when the continuous buffer is enabled, the state of the \phpseclib\Crypt\*() object changes after each
|
1504 |
-
* encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
|
1505 |
-
* continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
|
1506 |
-
* however, they are also less intuitive and more likely to cause you problems.
|
1507 |
-
*
|
1508 |
-
* @see self::disableContinuousBuffer()
|
1509 |
-
* @access public
|
1510 |
-
* @internal Could, but not must, extend by the child Crypt_* class
|
1511 |
-
*/
|
1512 |
-
function enableContinuousBuffer()
|
1513 |
-
{
|
1514 |
-
if ($this->mode == self::MODE_ECB) {
|
1515 |
-
return;
|
1516 |
-
}
|
1517 |
-
|
1518 |
-
$this->continuousBuffer = true;
|
1519 |
-
|
1520 |
-
$this->_setEngine();
|
1521 |
-
}
|
1522 |
-
|
1523 |
-
/**
|
1524 |
-
* Treat consecutive packets as if they are a discontinuous buffer.
|
1525 |
-
*
|
1526 |
-
* The default behavior.
|
1527 |
-
*
|
1528 |
-
* @see self::enableContinuousBuffer()
|
1529 |
-
* @access public
|
1530 |
-
* @internal Could, but not must, extend by the child Crypt_* class
|
1531 |
-
*/
|
1532 |
-
function disableContinuousBuffer()
|
1533 |
-
{
|
1534 |
-
if ($this->mode == self::MODE_ECB) {
|
1535 |
-
return;
|
1536 |
-
}
|
1537 |
-
if (!$this->continuousBuffer) {
|
1538 |
-
return;
|
1539 |
-
}
|
1540 |
-
|
1541 |
-
$this->continuousBuffer = false;
|
1542 |
-
$this->changed = true;
|
1543 |
-
|
1544 |
-
$this->_setEngine();
|
1545 |
-
}
|
1546 |
-
|
1547 |
-
/**
|
1548 |
-
* Test for engine validity
|
1549 |
-
*
|
1550 |
-
* @see self::__construct()
|
1551 |
-
* @param int $engine
|
1552 |
-
* @access public
|
1553 |
-
* @return bool
|
1554 |
-
*/
|
1555 |
-
function isValidEngine($engine)
|
1556 |
-
{
|
1557 |
-
switch ($engine) {
|
1558 |
-
case self::ENGINE_OPENSSL:
|
1559 |
-
if ($this->mode == self::MODE_STREAM && $this->continuousBuffer) {
|
1560 |
-
return false;
|
1561 |
-
}
|
1562 |
-
$this->openssl_emulate_ctr = false;
|
1563 |
-
$result = $this->cipher_name_openssl &&
|
1564 |
-
extension_loaded('openssl') &&
|
1565 |
-
// PHP 5.3.0 - 5.3.2 did not let you set IV's
|
1566 |
-
version_compare(PHP_VERSION, '5.3.3', '>=');
|
1567 |
-
if (!$result) {
|
1568 |
-
return false;
|
1569 |
-
}
|
1570 |
-
|
1571 |
-
// prior to PHP 5.4.0 OPENSSL_RAW_DATA and OPENSSL_ZERO_PADDING were not defined. instead of expecting an integer
|
1572 |
-
// $options openssl_encrypt expected a boolean $raw_data.
|
1573 |
-
if (!defined('OPENSSL_RAW_DATA')) {
|
1574 |
-
$this->openssl_options = true;
|
1575 |
-
} else {
|
1576 |
-
$this->openssl_options = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING;
|
1577 |
-
}
|
1578 |
-
|
1579 |
-
$methods = openssl_get_cipher_methods();
|
1580 |
-
if (in_array($this->cipher_name_openssl, $methods)) {
|
1581 |
-
return true;
|
1582 |
-
}
|
1583 |
-
// not all of openssl's symmetric cipher's support ctr. for those
|
1584 |
-
// that don't we'll emulate it
|
1585 |
-
switch ($this->mode) {
|
1586 |
-
case self::MODE_CTR:
|
1587 |
-
if (in_array($this->cipher_name_openssl_ecb, $methods)) {
|
1588 |
-
$this->openssl_emulate_ctr = true;
|
1589 |
-
return true;
|
1590 |
-
}
|
1591 |
-
}
|
1592 |
-
return false;
|
1593 |
-
case self::ENGINE_MCRYPT:
|
1594 |
-
return $this->cipher_name_mcrypt &&
|
1595 |
-
extension_loaded('mcrypt') &&
|
1596 |
-
in_array($this->cipher_name_mcrypt, @mcrypt_list_algorithms());
|
1597 |
-
case self::ENGINE_INTERNAL:
|
1598 |
-
return true;
|
1599 |
-
}
|
1600 |
-
|
1601 |
-
return false;
|
1602 |
-
}
|
1603 |
-
|
1604 |
-
/**
|
1605 |
-
* Sets the preferred crypt engine
|
1606 |
-
*
|
1607 |
-
* Currently, $engine could be:
|
1608 |
-
*
|
1609 |
-
* - \phpseclib\Crypt\Base::ENGINE_OPENSSL [very fast]
|
1610 |
-
*
|
1611 |
-
* - \phpseclib\Crypt\Base::ENGINE_MCRYPT [fast]
|
1612 |
-
*
|
1613 |
-
* - \phpseclib\Crypt\Base::ENGINE_INTERNAL [slow]
|
1614 |
-
*
|
1615 |
-
* If the preferred crypt engine is not available the fastest available one will be used
|
1616 |
-
*
|
1617 |
-
* @see self::__construct()
|
1618 |
-
* @param int $engine
|
1619 |
-
* @access public
|
1620 |
-
*/
|
1621 |
-
function setPreferredEngine($engine)
|
1622 |
-
{
|
1623 |
-
switch ($engine) {
|
1624 |
-
//case self::ENGINE_OPENSSL;
|
1625 |
-
case self::ENGINE_MCRYPT:
|
1626 |
-
case self::ENGINE_INTERNAL:
|
1627 |
-
$this->preferredEngine = $engine;
|
1628 |
-
break;
|
1629 |
-
default:
|
1630 |
-
$this->preferredEngine = self::ENGINE_OPENSSL;
|
1631 |
-
}
|
1632 |
-
|
1633 |
-
$this->_setEngine();
|
1634 |
-
}
|
1635 |
-
|
1636 |
-
/**
|
1637 |
-
* Returns the engine currently being utilized
|
1638 |
-
*
|
1639 |
-
* @see self::_setEngine()
|
1640 |
-
* @access public
|
1641 |
-
*/
|
1642 |
-
function getEngine()
|
1643 |
-
{
|
1644 |
-
return $this->engine;
|
1645 |
-
}
|
1646 |
-
|
1647 |
-
/**
|
1648 |
-
* Sets the engine as appropriate
|
1649 |
-
*
|
1650 |
-
* @see self::__construct()
|
1651 |
-
* @access private
|
1652 |
-
*/
|
1653 |
-
function _setEngine()
|
1654 |
-
{
|
1655 |
-
$this->engine = null;
|
1656 |
-
|
1657 |
-
$candidateEngines = array(
|
1658 |
-
$this->preferredEngine,
|
1659 |
-
self::ENGINE_OPENSSL,
|
1660 |
-
self::ENGINE_MCRYPT
|
1661 |
-
);
|
1662 |
-
foreach ($candidateEngines as $engine) {
|
1663 |
-
if ($this->isValidEngine($engine)) {
|
1664 |
-
$this->engine = $engine;
|
1665 |
-
break;
|
1666 |
-
}
|
1667 |
-
}
|
1668 |
-
if (!$this->engine) {
|
1669 |
-
$this->engine = self::ENGINE_INTERNAL;
|
1670 |
-
}
|
1671 |
-
|
1672 |
-
if ($this->engine != self::ENGINE_MCRYPT && $this->enmcrypt) {
|
1673 |
-
// Closing the current mcrypt resource(s). _mcryptSetup() will, if needed,
|
1674 |
-
// (re)open them with the module named in $this->cipher_name_mcrypt
|
1675 |
-
@mcrypt_module_close($this->enmcrypt);
|
1676 |
-
@mcrypt_module_close($this->demcrypt);
|
1677 |
-
$this->enmcrypt = null;
|
1678 |
-
$this->demcrypt = null;
|
1679 |
-
|
1680 |
-
if ($this->ecb) {
|
1681 |
-
@mcrypt_module_close($this->ecb);
|
1682 |
-
$this->ecb = null;
|
1683 |
-
}
|
1684 |
-
}
|
1685 |
-
|
1686 |
-
$this->changed = true;
|
1687 |
-
}
|
1688 |
-
|
1689 |
-
/**
|
1690 |
-
* Encrypts a block
|
1691 |
-
*
|
1692 |
-
* Note: Must be extended by the child \phpseclib\Crypt\* class
|
1693 |
-
*
|
1694 |
-
* @access private
|
1695 |
-
* @param string $in
|
1696 |
-
* @return string
|
1697 |
-
*/
|
1698 |
-
abstract function _encryptBlock($in);
|
1699 |
-
|
1700 |
-
/**
|
1701 |
-
* Decrypts a block
|
1702 |
-
*
|
1703 |
-
* Note: Must be extended by the child \phpseclib\Crypt\* class
|
1704 |
-
*
|
1705 |
-
* @access private
|
1706 |
-
* @param string $in
|
1707 |
-
* @return string
|
1708 |
-
*/
|
1709 |
-
abstract function _decryptBlock($in);
|
1710 |
-
|
1711 |
-
/**
|
1712 |
-
* Setup the key (expansion)
|
1713 |
-
*
|
1714 |
-
* Only used if $engine == self::ENGINE_INTERNAL
|
1715 |
-
*
|
1716 |
-
* Note: Must extend by the child \phpseclib\Crypt\* class
|
1717 |
-
*
|
1718 |
-
* @see self::_setup()
|
1719 |
-
* @access private
|
1720 |
-
*/
|
1721 |
-
abstract function _setupKey();
|
1722 |
-
|
1723 |
-
/**
|
1724 |
-
* Setup the self::ENGINE_INTERNAL $engine
|
1725 |
-
*
|
1726 |
-
* (re)init, if necessary, the internal cipher $engine and flush all $buffers
|
1727 |
-
* Used (only) if $engine == self::ENGINE_INTERNAL
|
1728 |
-
*
|
1729 |
-
* _setup() will be called each time if $changed === true
|
1730 |
-
* typically this happens when using one or more of following public methods:
|
1731 |
-
*
|
1732 |
-
* - setKey()
|
1733 |
-
*
|
1734 |
-
* - setIV()
|
1735 |
-
*
|
1736 |
-
* - disableContinuousBuffer()
|
1737 |
-
*
|
1738 |
-
* - First run of encrypt() / decrypt() with no init-settings
|
1739 |
-
*
|
1740 |
-
* @see self::setKey()
|
1741 |
-
* @see self::setIV()
|
1742 |
-
* @see self::disableContinuousBuffer()
|
1743 |
-
* @access private
|
1744 |
-
* @internal _setup() is always called before en/decryption.
|
1745 |
-
* @internal Could, but not must, extend by the child Crypt_* class
|
1746 |
-
*/
|
1747 |
-
function _setup()
|
1748 |
-
{
|
1749 |
-
$this->_clearBuffers();
|
1750 |
-
$this->_setupKey();
|
1751 |
-
|
1752 |
-
if ($this->use_inline_crypt) {
|
1753 |
-
$this->_setupInlineCrypt();
|
1754 |
-
}
|
1755 |
-
}
|
1756 |
-
|
1757 |
-
/**
|
1758 |
-
* Setup the self::ENGINE_MCRYPT $engine
|
1759 |
-
*
|
1760 |
-
* (re)init, if necessary, the (ext)mcrypt resources and flush all $buffers
|
1761 |
-
* Used (only) if $engine = self::ENGINE_MCRYPT
|
1762 |
-
*
|
1763 |
-
* _setupMcrypt() will be called each time if $changed === true
|
1764 |
-
* typically this happens when using one or more of following public methods:
|
1765 |
-
*
|
1766 |
-
* - setKey()
|
1767 |
-
*
|
1768 |
-
* - setIV()
|
1769 |
-
*
|
1770 |
-
* - disableContinuousBuffer()
|
1771 |
-
*
|
1772 |
-
* - First run of encrypt() / decrypt()
|
1773 |
-
*
|
1774 |
-
* @see self::setKey()
|
1775 |
-
* @see self::setIV()
|
1776 |
-
* @see self::disableContinuousBuffer()
|
1777 |
-
* @access private
|
1778 |
-
* @internal Could, but not must, extend by the child Crypt_* class
|
1779 |
-
*/
|
1780 |
-
function _setupMcrypt()
|
1781 |
-
{
|
1782 |
-
$this->_clearBuffers();
|
1783 |
-
$this->enchanged = $this->dechanged = true;
|
1784 |
-
|
1785 |
-
if (!isset($this->enmcrypt)) {
|
1786 |
-
static $mcrypt_modes = array(
|
1787 |
-
self::MODE_CTR => 'ctr',
|
1788 |
-
self::MODE_ECB => MCRYPT_MODE_ECB,
|
1789 |
-
self::MODE_CBC => MCRYPT_MODE_CBC,
|
1790 |
-
self::MODE_CFB => 'ncfb',
|
1791 |
-
self::MODE_OFB => MCRYPT_MODE_NOFB,
|
1792 |
-
self::MODE_STREAM => MCRYPT_MODE_STREAM,
|
1793 |
-
);
|
1794 |
-
|
1795 |
-
$this->demcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
|
1796 |
-
$this->enmcrypt = @mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
|
1797 |
-
|
1798 |
-
// we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer()
|
1799 |
-
// to workaround mcrypt's broken ncfb implementation in buffered mode
|
1800 |
-
// see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
|
1801 |
-
if ($this->mode == self::MODE_CFB) {
|
1802 |
-
$this->ecb = @mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, '');
|
1803 |
-
}
|
1804 |
-
} // else should mcrypt_generic_deinit be called?
|
1805 |
-
|
1806 |
-
if ($this->mode == self::MODE_CFB) {
|
1807 |
-
@mcrypt_generic_init($this->ecb, $this->key, str_repeat("\0", $this->block_size));
|
1808 |
-
}
|
1809 |
-
}
|
1810 |
-
|
1811 |
-
/**
|
1812 |
-
* Pads a string
|
1813 |
-
*
|
1814 |
-
* Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize.
|
1815 |
-
* $this->block_size - (strlen($text) % $this->block_size) bytes are added, each of which is equal to
|
1816 |
-
* chr($this->block_size - (strlen($text) % $this->block_size)
|
1817 |
-
*
|
1818 |
-
* If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
|
1819 |
-
* and padding will, hence forth, be enabled.
|
1820 |
-
*
|
1821 |
-
* @see self::_unpad()
|
1822 |
-
* @param string $text
|
1823 |
-
* @access private
|
1824 |
-
* @return string
|
1825 |
-
*/
|
1826 |
-
function _pad($text)
|
1827 |
-
{
|
1828 |
-
$length = strlen($text);
|
1829 |
-
|
1830 |
-
if (!$this->padding) {
|
1831 |
-
if ($length % $this->block_size == 0) {
|
1832 |
-
return $text;
|
1833 |
-
} else {
|
1834 |
-
user_error("The plaintext's length ($length) is not a multiple of the block size ({$this->block_size})");
|
1835 |
-
$this->padding = true;
|
1836 |
-
}
|
1837 |
-
}
|
1838 |
-
|
1839 |
-
$pad = $this->block_size - ($length % $this->block_size);
|
1840 |
-
|
1841 |
-
return str_pad($text, $length + $pad, chr($pad));
|
1842 |
-
}
|
1843 |
-
|
1844 |
-
/**
|
1845 |
-
* Unpads a string.
|
1846 |
-
*
|
1847 |
-
* If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
|
1848 |
-
* and false will be returned.
|
1849 |
-
*
|
1850 |
-
* @see self::_pad()
|
1851 |
-
* @param string $text
|
1852 |
-
* @access private
|
1853 |
-
* @return string
|
1854 |
-
*/
|
1855 |
-
function _unpad($text)
|
1856 |
-
{
|
1857 |
-
if (!$this->padding) {
|
1858 |
-
return $text;
|
1859 |
-
}
|
1860 |
-
|
1861 |
-
$length = ord($text[strlen($text) - 1]);
|
1862 |
-
|
1863 |
-
if (!$length || $length > $this->block_size) {
|
1864 |
-
return false;
|
1865 |
-
}
|
1866 |
-
|
1867 |
-
return substr($text, 0, -$length);
|
1868 |
-
}
|
1869 |
-
|
1870 |
-
/**
|
1871 |
-
* Clears internal buffers
|
1872 |
-
*
|
1873 |
-
* Clearing/resetting the internal buffers is done everytime
|
1874 |
-
* after disableContinuousBuffer() or on cipher $engine (re)init
|
1875 |
-
* ie after setKey() or setIV()
|
1876 |
-
*
|
1877 |
-
* @access public
|
1878 |
-
* @internal Could, but not must, extend by the child Crypt_* class
|
1879 |
-
*/
|
1880 |
-
function _clearBuffers()
|
1881 |
-
{
|
1882 |
-
$this->enbuffer = $this->debuffer = array('ciphertext' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true);
|
1883 |
-
|
1884 |
-
// mcrypt's handling of invalid's $iv:
|
1885 |
-
// $this->encryptIV = $this->decryptIV = strlen($this->iv) == $this->block_size ? $this->iv : str_repeat("\0", $this->block_size);
|
1886 |
-
$this->encryptIV = $this->decryptIV = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, "\0");
|
1887 |
-
|
1888 |
-
if (!$this->skip_key_adjustment) {
|
1889 |
-
$this->key = str_pad(substr($this->key, 0, $this->key_length), $this->key_length, "\0");
|
1890 |
-
}
|
1891 |
-
}
|
1892 |
-
|
1893 |
-
/**
|
1894 |
-
* String Shift
|
1895 |
-
*
|
1896 |
-
* Inspired by array_shift
|
1897 |
-
*
|
1898 |
-
* @param string $string
|
1899 |
-
* @param int $index
|
1900 |
-
* @access private
|
1901 |
-
* @return string
|
1902 |
-
*/
|
1903 |
-
function _string_shift(&$string, $index = 1)
|
1904 |
-
{
|
1905 |
-
$substr = substr($string, 0, $index);
|
1906 |
-
$string = substr($string, $index);
|
1907 |
-
return $substr;
|
1908 |
-
}
|
1909 |
-
|
1910 |
-
/**
|
1911 |
-
* String Pop
|
1912 |
-
*
|
1913 |
-
* Inspired by array_pop
|
1914 |
-
*
|
1915 |
-
* @param string $string
|
1916 |
-
* @param int $index
|
1917 |
-
* @access private
|
1918 |
-
* @return string
|
1919 |
-
*/
|
1920 |
-
function _string_pop(&$string, $index = 1)
|
1921 |
-
{
|
1922 |
-
$substr = substr($string, -$index);
|
1923 |
-
$string = substr($string, 0, -$index);
|
1924 |
-
return $substr;
|
1925 |
-
}
|
1926 |
-
|
1927 |
-
/**
|
1928 |
-
* Increment the current string
|
1929 |
-
*
|
1930 |
-
* @see self::decrypt()
|
1931 |
-
* @see self::encrypt()
|
1932 |
-
* @param string $var
|
1933 |
-
* @access private
|
1934 |
-
*/
|
1935 |
-
function _increment_str(&$var)
|
1936 |
-
{
|
1937 |
-
for ($i = 4; $i <= strlen($var); $i+= 4) {
|
1938 |
-
$temp = substr($var, -$i, 4);
|
1939 |
-
switch ($temp) {
|
1940 |
-
case "\xFF\xFF\xFF\xFF":
|
1941 |
-
$var = substr_replace($var, "\x00\x00\x00\x00", -$i, 4);
|
1942 |
-
break;
|
1943 |
-
case "\x7F\xFF\xFF\xFF":
|
1944 |
-
$var = substr_replace($var, "\x80\x00\x00\x00", -$i, 4);
|
1945 |
-
return;
|
1946 |
-
default:
|
1947 |
-
$temp = unpack('Nnum', $temp);
|
1948 |
-
$var = substr_replace($var, pack('N', $temp['num'] + 1), -$i, 4);
|
1949 |
-
return;
|
1950 |
-
}
|
1951 |
-
}
|
1952 |
-
|
1953 |
-
$remainder = strlen($var) % 4;
|
1954 |
-
|
1955 |
-
if ($remainder == 0) {
|
1956 |
-
return;
|
1957 |
-
}
|
1958 |
-
|
1959 |
-
$temp = unpack('Nnum', str_pad(substr($var, 0, $remainder), 4, "\0", STR_PAD_LEFT));
|
1960 |
-
$temp = substr(pack('N', $temp['num'] + 1), -$remainder);
|
1961 |
-
$var = substr_replace($var, $temp, 0, $remainder);
|
1962 |
-
}
|
1963 |
-
|
1964 |
-
/**
|
1965 |
-
* Setup the performance-optimized function for de/encrypt()
|
1966 |
-
*
|
1967 |
-
* Stores the created (or existing) callback function-name
|
1968 |
-
* in $this->inline_crypt
|
1969 |
-
*
|
1970 |
-
* Internally for phpseclib developers:
|
1971 |
-
*
|
1972 |
-
* _setupInlineCrypt() would be called only if:
|
1973 |
-
*
|
1974 |
-
* - $engine == self::ENGINE_INTERNAL and
|
1975 |
-
*
|
1976 |
-
* - $use_inline_crypt === true
|
1977 |
-
*
|
1978 |
-
* - each time on _setup(), after(!) _setupKey()
|
1979 |
-
*
|
1980 |
-
*
|
1981 |
-
* This ensures that _setupInlineCrypt() has always a
|
1982 |
-
* full ready2go initializated internal cipher $engine state
|
1983 |
-
* where, for example, the keys allready expanded,
|
1984 |
-
* keys/block_size calculated and such.
|
1985 |
-
*
|
1986 |
-
* It is, each time if called, the responsibility of _setupInlineCrypt():
|
1987 |
-
*
|
1988 |
-
* - to set $this->inline_crypt to a valid and fully working callback function
|
1989 |
-
* as a (faster) replacement for encrypt() / decrypt()
|
1990 |
-
*
|
1991 |
-
* - NOT to create unlimited callback functions (for memory reasons!)
|
1992 |
-
* no matter how often _setupInlineCrypt() would be called. At some
|
1993 |
-
* point of amount they must be generic re-useable.
|
1994 |
-
*
|
1995 |
-
* - the code of _setupInlineCrypt() it self,
|
1996 |
-
* and the generated callback code,
|
1997 |
-
* must be, in following order:
|
1998 |
-
* - 100% safe
|
1999 |
-
* - 100% compatible to encrypt()/decrypt()
|
2000 |
-
* - using only php5+ features/lang-constructs/php-extensions if
|
2001 |
-
* compatibility (down to php4) or fallback is provided
|
2002 |
-
* - readable/maintainable/understandable/commented and... not-cryptic-styled-code :-)
|
2003 |
-
* - >= 10% faster than encrypt()/decrypt() [which is, by the way,
|
2004 |
-
* the reason for the existence of _setupInlineCrypt() :-)]
|
2005 |
-
* - memory-nice
|
2006 |
-
* - short (as good as possible)
|
2007 |
-
*
|
2008 |
-
* Note: - _setupInlineCrypt() is using _createInlineCryptFunction() to create the full callback function code.
|
2009 |
-
* - In case of using inline crypting, _setupInlineCrypt() must extend by the child \phpseclib\Crypt\* class.
|
2010 |
-
* - The following variable names are reserved:
|
2011 |
-
* - $_* (all variable names prefixed with an underscore)
|
2012 |
-
* - $self (object reference to it self. Do not use $this, but $self instead)
|
2013 |
-
* - $in (the content of $in has to en/decrypt by the generated code)
|
2014 |
-
* - The callback function should not use the 'return' statement, but en/decrypt'ing the content of $in only
|
2015 |
-
*
|
2016 |
-
*
|
2017 |
-
* @see self::_setup()
|
2018 |
-
* @see self::_createInlineCryptFunction()
|
2019 |
-
* @see self::encrypt()
|
2020 |
-
* @see self::decrypt()
|
2021 |
-
* @access private
|
2022 |
-
* @internal If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt()
|
2023 |
-
*/
|
2024 |
-
function _setupInlineCrypt()
|
2025 |
-
{
|
2026 |
-
// If, for any reason, an extending \phpseclib\Crypt\Base() \phpseclib\Crypt\* class
|
2027 |
-
// not using inline crypting then it must be ensured that: $this->use_inline_crypt = false
|
2028 |
-
// ie in the class var declaration of $use_inline_crypt in general for the \phpseclib\Crypt\* class,
|
2029 |
-
// in the constructor at object instance-time
|
2030 |
-
// or, if it's runtime-specific, at runtime
|
2031 |
-
|
2032 |
-
$this->use_inline_crypt = false;
|
2033 |
-
}
|
2034 |
-
|
2035 |
-
/**
|
2036 |
-
* Creates the performance-optimized function for en/decrypt()
|
2037 |
-
*
|
2038 |
-
* Internally for phpseclib developers:
|
2039 |
-
*
|
2040 |
-
* _createInlineCryptFunction():
|
2041 |
-
*
|
2042 |
-
* - merge the $cipher_code [setup'ed by _setupInlineCrypt()]
|
2043 |
-
* with the current [$this->]mode of operation code
|
2044 |
-
*
|
2045 |
-
* - create the $inline function, which called by encrypt() / decrypt()
|
2046 |
-
* as its replacement to speed up the en/decryption operations.
|
2047 |
-
*
|
2048 |
-
* - return the name of the created $inline callback function
|
2049 |
-
*
|
2050 |
-
* - used to speed up en/decryption
|
2051 |
-
*
|
2052 |
-
*
|
2053 |
-
*
|
2054 |
-
* The main reason why can speed up things [up to 50%] this way are:
|
2055 |
-
*
|
2056 |
-
* - using variables more effective then regular.
|
2057 |
-
* (ie no use of expensive arrays but integers $k_0, $k_1 ...
|
2058 |
-
* or even, for example, the pure $key[] values hardcoded)
|
2059 |
-
*
|
2060 |
-
* - avoiding 1000's of function calls of ie _encryptBlock()
|
2061 |
-
* but inlining the crypt operations.
|
2062 |
-
* in the mode of operation for() loop.
|
2063 |
-
*
|
2064 |
-
* - full loop unroll the (sometimes key-dependent) rounds
|
2065 |
-
* avoiding this way ++$i counters and runtime-if's etc...
|
2066 |
-
*
|
2067 |
-
* The basic code architectur of the generated $inline en/decrypt()
|
2068 |
-
* lambda function, in pseudo php, is:
|
2069 |
-
*
|
2070 |
-
* <code>
|
2071 |
-
* +----------------------------------------------------------------------------------------------+
|
2072 |
-
* | callback $inline = create_function: |
|
2073 |
-
* | lambda_function_0001_crypt_ECB($action, $text) |
|
2074 |
-
* | { |
|
2075 |
-
* | INSERT PHP CODE OF: |
|
2076 |
-
* | $cipher_code['init_crypt']; // general init code. |
|
2077 |
-
* | // ie: $sbox'es declarations used for |
|
2078 |
-
* | // encrypt and decrypt'ing. |
|
2079 |
-
* | |
|
2080 |
-
* | switch ($action) { |
|
2081 |
-
* | case 'encrypt': |
|
2082 |
-
* | INSERT PHP CODE OF: |
|
2083 |
-
* | $cipher_code['init_encrypt']; // encrypt sepcific init code. |
|
2084 |
-
* | ie: specified $key or $box |
|
2085 |
-
* | declarations for encrypt'ing. |
|
2086 |
-
* | |
|
2087 |
-
* | foreach ($ciphertext) { |
|
2088 |
-
* | $in = $block_size of $ciphertext; |
|
2089 |
-
* | |
|
2090 |
-
* | INSERT PHP CODE OF: |
|
2091 |
-
* | $cipher_code['encrypt_block']; // encrypt's (string) $in, which is always: |
|
2092 |
-
* | // strlen($in) == $this->block_size |
|
2093 |
-
* | // here comes the cipher algorithm in action |
|
2094 |
-
* | // for encryption. |
|
2095 |
-
* | // $cipher_code['encrypt_block'] has to |
|
2096 |
-
* | // encrypt the content of the $in variable |
|
2097 |
-
* | |
|
2098 |
-
* | $plaintext .= $in; |
|
2099 |
-
* | } |
|
2100 |
-
* | return $plaintext; |
|
2101 |
-
* | |
|
2102 |
-
* | case 'decrypt': |
|
2103 |
-
* | INSERT PHP CODE OF: |
|
2104 |
-
* | $cipher_code['init_decrypt']; // decrypt sepcific init code |
|
2105 |
-
* | ie: specified $key or $box |
|
2106 |
-
* | declarations for decrypt'ing. |
|
2107 |
-
* | foreach ($plaintext) { |
|
2108 |
-
* | $in = $block_size of $plaintext; |
|
2109 |
-
* | |
|
2110 |
-
* | INSERT PHP CODE OF: |
|
2111 |
-
* | $cipher_code['decrypt_block']; // decrypt's (string) $in, which is always |
|
2112 |
-
* | // strlen($in) == $this->block_size |
|
2113 |
-
* | // here comes the cipher algorithm in action |
|
2114 |
-
* | // for decryption. |
|
2115 |
-
* | // $cipher_code['decrypt_block'] has to |
|
2116 |
-
* | // decrypt the content of the $in variable |
|
2117 |
-
* | $ciphertext .= $in; |
|
2118 |
-
* | } |
|
2119 |
-
* | return $ciphertext; |
|
2120 |
-
* | } |
|
2121 |
-
* | } |
|
2122 |
-
* +----------------------------------------------------------------------------------------------+
|
2123 |
-
* </code>
|
2124 |
-
*
|
2125 |
-
* See also the \phpseclib\Crypt\*::_setupInlineCrypt()'s for
|
2126 |
-
* productive inline $cipher_code's how they works.
|
2127 |
-
*
|
2128 |
-
* Structure of:
|
2129 |
-
* <code>
|
2130 |
-
* $cipher_code = array(
|
2131 |
-
* 'init_crypt' => (string) '', // optional
|
2132 |
-
* 'init_encrypt' => (string) '', // optional
|
2133 |
-
* 'init_decrypt' => (string) '', // optional
|
2134 |
-
* 'encrypt_block' => (string) '', // required
|
2135 |
-
* 'decrypt_block' => (string) '' // required
|
2136 |
-
* );
|
2137 |
-
* </code>
|
2138 |
-
*
|
2139 |
-
* @see self::_setupInlineCrypt()
|
2140 |
-
* @see self::encrypt()
|
2141 |
-
* @see self::decrypt()
|
2142 |
-
* @param array $cipher_code
|
2143 |
-
* @access private
|
2144 |
-
* @return string (the name of the created callback function)
|
2145 |
-
*/
|
2146 |
-
function _createInlineCryptFunction($cipher_code)
|
2147 |
-
{
|
2148 |
-
$block_size = $this->block_size;
|
2149 |
-
|
2150 |
-
// optional
|
2151 |
-
$init_crypt = isset($cipher_code['init_crypt']) ? $cipher_code['init_crypt'] : '';
|
2152 |
-
$init_encrypt = isset($cipher_code['init_encrypt']) ? $cipher_code['init_encrypt'] : '';
|
2153 |
-
$init_decrypt = isset($cipher_code['init_decrypt']) ? $cipher_code['init_decrypt'] : '';
|
2154 |
-
// required
|
2155 |
-
$encrypt_block = $cipher_code['encrypt_block'];
|
2156 |
-
$decrypt_block = $cipher_code['decrypt_block'];
|
2157 |
-
|
2158 |
-
// Generating mode of operation inline code,
|
2159 |
-
// merged with the $cipher_code algorithm
|
2160 |
-
// for encrypt- and decryption.
|
2161 |
-
switch ($this->mode) {
|
2162 |
-
case self::MODE_ECB:
|
2163 |
-
$encrypt = $init_encrypt . '
|
2164 |
-
$_ciphertext = "";
|
2165 |
-
$_plaintext_len = strlen($_text);
|
2166 |
-
|
2167 |
-
for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
|
2168 |
-
$in = substr($_text, $_i, '.$block_size.');
|
2169 |
-
'.$encrypt_block.'
|
2170 |
-
$_ciphertext.= $in;
|
2171 |
-
}
|
2172 |
-
|
2173 |
-
return $_ciphertext;
|
2174 |
-
';
|
2175 |
-
|
2176 |
-
$decrypt = $init_decrypt . '
|
2177 |
-
$_plaintext = "";
|
2178 |
-
$_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
|
2179 |
-
$_ciphertext_len = strlen($_text);
|
2180 |
-
|
2181 |
-
for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
|
2182 |
-
$in = substr($_text, $_i, '.$block_size.');
|
2183 |
-
'.$decrypt_block.'
|
2184 |
-
$_plaintext.= $in;
|
2185 |
-
}
|
2186 |
-
|
2187 |
-
return $self->_unpad($_plaintext);
|
2188 |
-
';
|
2189 |
-
break;
|
2190 |
-
case self::MODE_CTR:
|
2191 |
-
$encrypt = $init_encrypt . '
|
2192 |
-
$_ciphertext = "";
|
2193 |
-
$_plaintext_len = strlen($_text);
|
2194 |
-
$_xor = $self->encryptIV;
|
2195 |
-
$_buffer = &$self->enbuffer;
|
2196 |
-
if (strlen($_buffer["ciphertext"])) {
|
2197 |
-
for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
|
2198 |
-
$_block = substr($_text, $_i, '.$block_size.');
|
2199 |
-
if (strlen($_block) > strlen($_buffer["ciphertext"])) {
|
2200 |
-
$in = $_xor;
|
2201 |
-
'.$encrypt_block.'
|
2202 |
-
$self->_increment_str($_xor);
|
2203 |
-
$_buffer["ciphertext"].= $in;
|
2204 |
-
}
|
2205 |
-
$_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
|
2206 |
-
$_ciphertext.= $_block ^ $_key;
|
2207 |
-
}
|
2208 |
-
} else {
|
2209 |
-
for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
|
2210 |
-
$_block = substr($_text, $_i, '.$block_size.');
|
2211 |
-
$in = $_xor;
|
2212 |
-
'.$encrypt_block.'
|
2213 |
-
$self->_increment_str($_xor);
|
2214 |
-
$_key = $in;
|
2215 |
-
$_ciphertext.= $_block ^ $_key;
|
2216 |
-
}
|
2217 |
-
}
|
2218 |
-
if ($self->continuousBuffer) {
|
2219 |
-
$self->encryptIV = $_xor;
|
2220 |
-
if ($_start = $_plaintext_len % '.$block_size.') {
|
2221 |
-
$_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
|
2222 |
-
}
|
2223 |
-
}
|
2224 |
-
|
2225 |
-
return $_ciphertext;
|
2226 |
-
';
|
2227 |
-
|
2228 |
-
$decrypt = $init_encrypt . '
|
2229 |
-
$_plaintext = "";
|
2230 |
-
$_ciphertext_len = strlen($_text);
|
2231 |
-
$_xor = $self->decryptIV;
|
2232 |
-
$_buffer = &$self->debuffer;
|
2233 |
-
|
2234 |
-
if (strlen($_buffer["ciphertext"])) {
|
2235 |
-
for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
|
2236 |
-
$_block = substr($_text, $_i, '.$block_size.');
|
2237 |
-
if (strlen($_block) > strlen($_buffer["ciphertext"])) {
|
2238 |
-
$in = $_xor;
|
2239 |
-
'.$encrypt_block.'
|
2240 |
-
$self->_increment_str($_xor);
|
2241 |
-
$_buffer["ciphertext"].= $in;
|
2242 |
-
}
|
2243 |
-
$_key = $self->_string_shift($_buffer["ciphertext"], '.$block_size.');
|
2244 |
-
$_plaintext.= $_block ^ $_key;
|
2245 |
-
}
|
2246 |
-
} else {
|
2247 |
-
for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
|
2248 |
-
$_block = substr($_text, $_i, '.$block_size.');
|
2249 |
-
$in = $_xor;
|
2250 |
-
'.$encrypt_block.'
|
2251 |
-
$self->_increment_str($_xor);
|
2252 |
-
$_key = $in;
|
2253 |
-
$_plaintext.= $_block ^ $_key;
|
2254 |
-
}
|
2255 |
-
}
|
2256 |
-
if ($self->continuousBuffer) {
|
2257 |
-
$self->decryptIV = $_xor;
|
2258 |
-
if ($_start = $_ciphertext_len % '.$block_size.') {
|
2259 |
-
$_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
|
2260 |
-
}
|
2261 |
-
}
|
2262 |
-
|
2263 |
-
return $_plaintext;
|
2264 |
-
';
|
2265 |
-
break;
|
2266 |
-
case self::MODE_CFB:
|
2267 |
-
$encrypt = $init_encrypt . '
|
2268 |
-
$_ciphertext = "";
|
2269 |
-
$_buffer = &$self->enbuffer;
|
2270 |
-
|
2271 |
-
if ($self->continuousBuffer) {
|
2272 |
-
$_iv = &$self->encryptIV;
|
2273 |
-
$_pos = &$_buffer["pos"];
|
2274 |
-
} else {
|
2275 |
-
$_iv = $self->encryptIV;
|
2276 |
-
$_pos = 0;
|
2277 |
-
}
|
2278 |
-
$_len = strlen($_text);
|
2279 |
-
$_i = 0;
|
2280 |
-
if ($_pos) {
|
2281 |
-
$_orig_pos = $_pos;
|
2282 |
-
$_max = '.$block_size.' - $_pos;
|
2283 |
-
if ($_len >= $_max) {
|
2284 |
-
$_i = $_max;
|
2285 |
-
$_len-= $_max;
|
2286 |
-
$_pos = 0;
|
2287 |
-
} else {
|
2288 |
-
$_i = $_len;
|
2289 |
-
$_pos+= $_len;
|
2290 |
-
$_len = 0;
|
2291 |
-
}
|
2292 |
-
$_ciphertext = substr($_iv, $_orig_pos) ^ $_text;
|
2293 |
-
$_iv = substr_replace($_iv, $_ciphertext, $_orig_pos, $_i);
|
2294 |
-
}
|
2295 |
-
while ($_len >= '.$block_size.') {
|
2296 |
-
$in = $_iv;
|
2297 |
-
'.$encrypt_block.';
|
2298 |
-
$_iv = $in ^ substr($_text, $_i, '.$block_size.');
|
2299 |
-
$_ciphertext.= $_iv;
|
2300 |
-
$_len-= '.$block_size.';
|
2301 |
-
$_i+= '.$block_size.';
|
2302 |
-
}
|
2303 |
-
if ($_len) {
|
2304 |
-
$in = $_iv;
|
2305 |
-
'.$encrypt_block.'
|
2306 |
-
$_iv = $in;
|
2307 |
-
$_block = $_iv ^ substr($_text, $_i);
|
2308 |
-
$_iv = substr_replace($_iv, $_block, 0, $_len);
|
2309 |
-
$_ciphertext.= $_block;
|
2310 |
-
$_pos = $_len;
|
2311 |
-
}
|
2312 |
-
return $_ciphertext;
|
2313 |
-
';
|
2314 |
-
|
2315 |
-
$decrypt = $init_encrypt . '
|
2316 |
-
$_plaintext = "";
|
2317 |
-
$_buffer = &$self->debuffer;
|
2318 |
-
|
2319 |
-
if ($self->continuousBuffer) {
|
2320 |
-
$_iv = &$self->decryptIV;
|
2321 |
-
$_pos = &$_buffer["pos"];
|
2322 |
-
} else {
|
2323 |
-
$_iv = $self->decryptIV;
|
2324 |
-
$_pos = 0;
|
2325 |
-
}
|
2326 |
-
$_len = strlen($_text);
|
2327 |
-
$_i = 0;
|
2328 |
-
if ($_pos) {
|
2329 |
-
$_orig_pos = $_pos;
|
2330 |
-
$_max = '.$block_size.' - $_pos;
|
2331 |
-
if ($_len >= $_max) {
|
2332 |
-
$_i = $_max;
|
2333 |
-
$_len-= $_max;
|
2334 |
-
$_pos = 0;
|
2335 |
-
} else {
|
2336 |
-
$_i = $_len;
|
2337 |
-
$_pos+= $_len;
|
2338 |
-
$_len = 0;
|
2339 |
-
}
|
2340 |
-
$_plaintext = substr($_iv, $_orig_pos) ^ $_text;
|
2341 |
-
$_iv = substr_replace($_iv, substr($_text, 0, $_i), $_orig_pos, $_i);
|
2342 |
-
}
|
2343 |
-
while ($_len >= '.$block_size.') {
|
2344 |
-
$in = $_iv;
|
2345 |
-
'.$encrypt_block.'
|
2346 |
-
$_iv = $in;
|
2347 |
-
$cb = substr($_text, $_i, '.$block_size.');
|
2348 |
-
$_plaintext.= $_iv ^ $cb;
|
2349 |
-
$_iv = $cb;
|
2350 |
-
$_len-= '.$block_size.';
|
2351 |
-
$_i+= '.$block_size.';
|
2352 |
-
}
|
2353 |
-
if ($_len) {
|
2354 |
-
$in = $_iv;
|
2355 |
-
'.$encrypt_block.'
|
2356 |
-
$_iv = $in;
|
2357 |
-
$_plaintext.= $_iv ^ substr($_text, $_i);
|
2358 |
-
$_iv = substr_replace($_iv, substr($_text, $_i), 0, $_len);
|
2359 |
-
$_pos = $_len;
|
2360 |
-
}
|
2361 |
-
|
2362 |
-
return $_plaintext;
|
2363 |
-
';
|
2364 |
-
break;
|
2365 |
-
case self::MODE_OFB:
|
2366 |
-
$encrypt = $init_encrypt . '
|
2367 |
-
$_ciphertext = "";
|
2368 |
-
$_plaintext_len = strlen($_text);
|
2369 |
-
$_xor = $self->encryptIV;
|
2370 |
-
$_buffer = &$self->enbuffer;
|
2371 |
-
|
2372 |
-
if (strlen($_buffer["xor"])) {
|
2373 |
-
for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
|
2374 |
-
$_block = substr($_text, $_i, '.$block_size.');
|
2375 |
-
if (strlen($_block) > strlen($_buffer["xor"])) {
|
2376 |
-
$in = $_xor;
|
2377 |
-
'.$encrypt_block.'
|
2378 |
-
$_xor = $in;
|
2379 |
-
$_buffer["xor"].= $_xor;
|
2380 |
-
}
|
2381 |
-
$_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
|
2382 |
-
$_ciphertext.= $_block ^ $_key;
|
2383 |
-
}
|
2384 |
-
} else {
|
2385 |
-
for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
|
2386 |
-
$in = $_xor;
|
2387 |
-
'.$encrypt_block.'
|
2388 |
-
$_xor = $in;
|
2389 |
-
$_ciphertext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
|
2390 |
-
}
|
2391 |
-
$_key = $_xor;
|
2392 |
-
}
|
2393 |
-
if ($self->continuousBuffer) {
|
2394 |
-
$self->encryptIV = $_xor;
|
2395 |
-
if ($_start = $_plaintext_len % '.$block_size.') {
|
2396 |
-
$_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
|
2397 |
-
}
|
2398 |
-
}
|
2399 |
-
return $_ciphertext;
|
2400 |
-
';
|
2401 |
-
|
2402 |
-
$decrypt = $init_encrypt . '
|
2403 |
-
$_plaintext = "";
|
2404 |
-
$_ciphertext_len = strlen($_text);
|
2405 |
-
$_xor = $self->decryptIV;
|
2406 |
-
$_buffer = &$self->debuffer;
|
2407 |
-
|
2408 |
-
if (strlen($_buffer["xor"])) {
|
2409 |
-
for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
|
2410 |
-
$_block = substr($_text, $_i, '.$block_size.');
|
2411 |
-
if (strlen($_block) > strlen($_buffer["xor"])) {
|
2412 |
-
$in = $_xor;
|
2413 |
-
'.$encrypt_block.'
|
2414 |
-
$_xor = $in;
|
2415 |
-
$_buffer["xor"].= $_xor;
|
2416 |
-
}
|
2417 |
-
$_key = $self->_string_shift($_buffer["xor"], '.$block_size.');
|
2418 |
-
$_plaintext.= $_block ^ $_key;
|
2419 |
-
}
|
2420 |
-
} else {
|
2421 |
-
for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
|
2422 |
-
$in = $_xor;
|
2423 |
-
'.$encrypt_block.'
|
2424 |
-
$_xor = $in;
|
2425 |
-
$_plaintext.= substr($_text, $_i, '.$block_size.') ^ $_xor;
|
2426 |
-
}
|
2427 |
-
$_key = $_xor;
|
2428 |
-
}
|
2429 |
-
if ($self->continuousBuffer) {
|
2430 |
-
$self->decryptIV = $_xor;
|
2431 |
-
if ($_start = $_ciphertext_len % '.$block_size.') {
|
2432 |
-
$_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
|
2433 |
-
}
|
2434 |
-
}
|
2435 |
-
return $_plaintext;
|
2436 |
-
';
|
2437 |
-
break;
|
2438 |
-
case self::MODE_STREAM:
|
2439 |
-
$encrypt = $init_encrypt . '
|
2440 |
-
$_ciphertext = "";
|
2441 |
-
'.$encrypt_block.'
|
2442 |
-
return $_ciphertext;
|
2443 |
-
';
|
2444 |
-
$decrypt = $init_decrypt . '
|
2445 |
-
$_plaintext = "";
|
2446 |
-
'.$decrypt_block.'
|
2447 |
-
return $_plaintext;
|
2448 |
-
';
|
2449 |
-
break;
|
2450 |
-
// case self::MODE_CBC:
|
2451 |
-
default:
|
2452 |
-
$encrypt = $init_encrypt . '
|
2453 |
-
$_ciphertext = "";
|
2454 |
-
$_plaintext_len = strlen($_text);
|
2455 |
-
|
2456 |
-
$in = $self->encryptIV;
|
2457 |
-
|
2458 |
-
for ($_i = 0; $_i < $_plaintext_len; $_i+= '.$block_size.') {
|
2459 |
-
$in = substr($_text, $_i, '.$block_size.') ^ $in;
|
2460 |
-
'.$encrypt_block.'
|
2461 |
-
$_ciphertext.= $in;
|
2462 |
-
}
|
2463 |
-
|
2464 |
-
if ($self->continuousBuffer) {
|
2465 |
-
$self->encryptIV = $in;
|
2466 |
-
}
|
2467 |
-
|
2468 |
-
return $_ciphertext;
|
2469 |
-
';
|
2470 |
-
|
2471 |
-
$decrypt = $init_decrypt . '
|
2472 |
-
$_plaintext = "";
|
2473 |
-
$_text = str_pad($_text, strlen($_text) + ('.$block_size.' - strlen($_text) % '.$block_size.') % '.$block_size.', chr(0));
|
2474 |
-
$_ciphertext_len = strlen($_text);
|
2475 |
-
|
2476 |
-
$_iv = $self->decryptIV;
|
2477 |
-
|
2478 |
-
for ($_i = 0; $_i < $_ciphertext_len; $_i+= '.$block_size.') {
|
2479 |
-
$in = $_block = substr($_text, $_i, '.$block_size.');
|
2480 |
-
'.$decrypt_block.'
|
2481 |
-
$_plaintext.= $in ^ $_iv;
|
2482 |
-
$_iv = $_block;
|
2483 |
-
}
|
2484 |
-
|
2485 |
-
if ($self->continuousBuffer) {
|
2486 |
-
$self->decryptIV = $_iv;
|
2487 |
-
}
|
2488 |
-
|
2489 |
-
return $self->_unpad($_plaintext);
|
2490 |
-
';
|
2491 |
-
break;
|
2492 |
-
}
|
2493 |
-
|
2494 |
-
// Create the $inline function and return its name as string. Ready to run!
|
2495 |
-
if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
|
2496 |
-
eval('$func = function ($_action, &$self, $_text) { ' . $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' } };');
|
2497 |
-
return $func;
|
2498 |
-
}
|
2499 |
-
|
2500 |
-
return create_function('$_action, &$self, $_text', $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }');
|
2501 |
-
}
|
2502 |
-
|
2503 |
-
/**
|
2504 |
-
* Holds the lambda_functions table (classwide)
|
2505 |
-
*
|
2506 |
-
* Each name of the lambda function, created from
|
2507 |
-
* _setupInlineCrypt() && _createInlineCryptFunction()
|
2508 |
-
* is stored, classwide (!), here for reusing.
|
2509 |
-
*
|
2510 |
-
* The string-based index of $function is a classwide
|
2511 |
-
* unique value representing, at least, the $mode of
|
2512 |
-
* operation (or more... depends of the optimizing level)
|
2513 |
-
* for which $mode the lambda function was created.
|
2514 |
-
*
|
2515 |
-
* @access private
|
2516 |
-
* @return array &$functions
|
2517 |
-
*/
|
2518 |
-
function &_getLambdaFunctions()
|
2519 |
-
{
|
2520 |
-
static $functions = array();
|
2521 |
-
return $functions;
|
2522 |
-
}
|
2523 |
-
|
2524 |
-
/**
|
2525 |
-
* Generates a digest from $bytes
|
2526 |
-
*
|
2527 |
-
* @see self::_setupInlineCrypt()
|
2528 |
-
* @access private
|
2529 |
-
* @param $bytes
|
2530 |
-
* @return string
|
2531 |
-
*/
|
2532 |
-
function _hashInlineCryptFunction($bytes)
|
2533 |
-
{
|
2534 |
-
if (!isset(self::$WHIRLPOOL_AVAILABLE)) {
|
2535 |
-
self::$WHIRLPOOL_AVAILABLE = extension_loaded('hash') && in_array('whirlpool', hash_algos());
|
2536 |
-
}
|
2537 |
-
|
2538 |
-
$result = '';
|
2539 |
-
$hash = $bytes;
|
2540 |
-
|
2541 |
-
switch (true) {
|
2542 |
-
case self::$WHIRLPOOL_AVAILABLE:
|
2543 |
-
foreach (str_split($bytes, 64) as $t) {
|
2544 |
-
$hash = hash('whirlpool', $hash, true);
|
2545 |
-
$result .= $t ^ $hash;
|
2546 |
-
}
|
2547 |
-
return $result . hash('whirlpool', $hash, true);
|
2548 |
-
default:
|
2549 |
-
$len = strlen($bytes);
|
2550 |
-
for ($i = 0; $i < $len; $i+=20) {
|
2551 |
-
$t = substr($bytes, $i, 20);
|
2552 |
-
$hash = pack('H*', sha1($hash));
|
2553 |
-
$result .= $t ^ $hash;
|
2554 |
-
}
|
2555 |
-
return $result . pack('H*', sha1($hash));
|
2556 |
-
}
|
2557 |
-
}
|
2558 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php
DELETED
@@ -1,577 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Pure-PHP implementation of Blowfish.
|
5 |
-
*
|
6 |
-
* Uses mcrypt, if available, and an internal implementation, otherwise.
|
7 |
-
*
|
8 |
-
* PHP version 5
|
9 |
-
*
|
10 |
-
* Useful resources are as follows:
|
11 |
-
*
|
12 |
-
* - {@link http://en.wikipedia.org/wiki/Blowfish_(cipher) Wikipedia description of Blowfish}
|
13 |
-
*
|
14 |
-
* Here's a short example of how to use this library:
|
15 |
-
* <code>
|
16 |
-
* <?php
|
17 |
-
* include 'vendor/autoload.php';
|
18 |
-
*
|
19 |
-
* $blowfish = new \phpseclib\Crypt\Blowfish();
|
20 |
-
*
|
21 |
-
* $blowfish->setKey('12345678901234567890123456789012');
|
22 |
-
*
|
23 |
-
* $plaintext = str_repeat('a', 1024);
|
24 |
-
*
|
25 |
-
* echo $blowfish->decrypt($blowfish->encrypt($plaintext));
|
26 |
-
* ?>
|
27 |
-
* </code>
|
28 |
-
*
|
29 |
-
* @category Crypt
|
30 |
-
* @package Blowfish
|
31 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
32 |
-
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
|
33 |
-
* @copyright 2007 Jim Wigginton
|
34 |
-
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
35 |
-
* @link http://phpseclib.sourceforge.net
|
36 |
-
*/
|
37 |
-
|
38 |
-
namespace phpseclib\Crypt;
|
39 |
-
|
40 |
-
/**
|
41 |
-
* Pure-PHP implementation of Blowfish.
|
42 |
-
*
|
43 |
-
* @package Blowfish
|
44 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
45 |
-
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
|
46 |
-
* @access public
|
47 |
-
*/
|
48 |
-
class Blowfish extends Base
|
49 |
-
{
|
50 |
-
/**
|
51 |
-
* Block Length of the cipher
|
52 |
-
*
|
53 |
-
* @see \phpseclib\Crypt\Base::block_size
|
54 |
-
* @var int
|
55 |
-
* @access private
|
56 |
-
*/
|
57 |
-
var $block_size = 8;
|
58 |
-
|
59 |
-
/**
|
60 |
-
* The mcrypt specific name of the cipher
|
61 |
-
*
|
62 |
-
* @see \phpseclib\Crypt\Base::cipher_name_mcrypt
|
63 |
-
* @var string
|
64 |
-
* @access private
|
65 |
-
*/
|
66 |
-
var $cipher_name_mcrypt = 'blowfish';
|
67 |
-
|
68 |
-
/**
|
69 |
-
* Optimizing value while CFB-encrypting
|
70 |
-
*
|
71 |
-
* @see \phpseclib\Crypt\Base::cfb_init_len
|
72 |
-
* @var int
|
73 |
-
* @access private
|
74 |
-
*/
|
75 |
-
var $cfb_init_len = 500;
|
76 |
-
|
77 |
-
/**
|
78 |
-
* The fixed subkeys boxes ($sbox0 - $sbox3) with 256 entries each
|
79 |
-
*
|
80 |
-
* S-Box 0
|
81 |
-
*
|
82 |
-
* @access private
|
83 |
-
* @var array
|
84 |
-
*/
|
85 |
-
var $sbox0 = array(
|
86 |
-
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
|
87 |
-
0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
|
88 |
-
0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
|
89 |
-
0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
|
90 |
-
0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
|
91 |
-
0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
|
92 |
-
0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
|
93 |
-
0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
|
94 |
-
0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
|
95 |
-
0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
|
96 |
-
0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
|
97 |
-
0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
|
98 |
-
0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
|
99 |
-
0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
|
100 |
-
0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
|
101 |
-
0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
|
102 |
-
0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
|
103 |
-
0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
|
104 |
-
0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
|
105 |
-
0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
|
106 |
-
0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
|
107 |
-
0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
|
108 |
-
0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
|
109 |
-
0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
|
110 |
-
0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
|
111 |
-
0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
|
112 |
-
0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
|
113 |
-
0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
|
114 |
-
0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
|
115 |
-
0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
|
116 |
-
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
|
117 |
-
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
|
118 |
-
);
|
119 |
-
|
120 |
-
/**
|
121 |
-
* S-Box 1
|
122 |
-
*
|
123 |
-
* @access private
|
124 |
-
* @var array
|
125 |
-
*/
|
126 |
-
var $sbox1 = array(
|
127 |
-
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
|
128 |
-
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
|
129 |
-
0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
|
130 |
-
0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
|
131 |
-
0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
|
132 |
-
0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
|
133 |
-
0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
|
134 |
-
0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
|
135 |
-
0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
|
136 |
-
0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
|
137 |
-
0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
|
138 |
-
0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
|
139 |
-
0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
|
140 |
-
0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
|
141 |
-
0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
|
142 |
-
0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
|
143 |
-
0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
|
144 |
-
0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
|
145 |
-
0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
|
146 |
-
0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
|
147 |
-
0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
|
148 |
-
0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
|
149 |
-
0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
|
150 |
-
0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
|
151 |
-
0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
|
152 |
-
0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
|
153 |
-
0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
|
154 |
-
0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
|
155 |
-
0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
|
156 |
-
0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
|
157 |
-
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
|
158 |
-
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
|
159 |
-
);
|
160 |
-
|
161 |
-
/**
|
162 |
-
* S-Box 2
|
163 |
-
*
|
164 |
-
* @access private
|
165 |
-
* @var array
|
166 |
-
*/
|
167 |
-
var $sbox2 = array(
|
168 |
-
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
|
169 |
-
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
|
170 |
-
0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
|
171 |
-
0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
|
172 |
-
0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
|
173 |
-
0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
|
174 |
-
0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
|
175 |
-
0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
|
176 |
-
0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
|
177 |
-
0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
|
178 |
-
0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
|
179 |
-
0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
|
180 |
-
0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
|
181 |
-
0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
|
182 |
-
0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
|
183 |
-
0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
|
184 |
-
0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
|
185 |
-
0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
|
186 |
-
0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
|
187 |
-
0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
|
188 |
-
0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
|
189 |
-
0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
|
190 |
-
0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
|
191 |
-
0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
|
192 |
-
0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
|
193 |
-
0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
|
194 |
-
0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
|
195 |
-
0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
|
196 |
-
0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
|
197 |
-
0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
|
198 |
-
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
|
199 |
-
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
|
200 |
-
);
|
201 |
-
|
202 |
-
/**
|
203 |
-
* S-Box 3
|
204 |
-
*
|
205 |
-
* @access private
|
206 |
-
* @var array
|
207 |
-
*/
|
208 |
-
var $sbox3 = array(
|
209 |
-
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
|
210 |
-
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
|
211 |
-
0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
|
212 |
-
0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
|
213 |
-
0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
|
214 |
-
0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
|
215 |
-
0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
|
216 |
-
0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
|
217 |
-
0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
|
218 |
-
0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
|
219 |
-
0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
|
220 |
-
0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
|
221 |
-
0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
|
222 |
-
0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
|
223 |
-
0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
|
224 |
-
0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
|
225 |
-
0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
|
226 |
-
0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
|
227 |
-
0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
|
228 |
-
0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
|
229 |
-
0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
|
230 |
-
0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
|
231 |
-
0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
|
232 |
-
0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
|
233 |
-
0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
|
234 |
-
0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
|
235 |
-
0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
|
236 |
-
0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
|
237 |
-
0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
|
238 |
-
0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
|
239 |
-
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
|
240 |
-
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
|
241 |
-
);
|
242 |
-
|
243 |
-
/**
|
244 |
-
* P-Array consists of 18 32-bit subkeys
|
245 |
-
*
|
246 |
-
* @var array
|
247 |
-
* @access private
|
248 |
-
*/
|
249 |
-
var $parray = array(
|
250 |
-
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
|
251 |
-
0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
|
252 |
-
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b
|
253 |
-
);
|
254 |
-
|
255 |
-
/**
|
256 |
-
* The BCTX-working Array
|
257 |
-
*
|
258 |
-
* Holds the expanded key [p] and the key-depended s-boxes [sb]
|
259 |
-
*
|
260 |
-
* @var array
|
261 |
-
* @access private
|
262 |
-
*/
|
263 |
-
var $bctx;
|
264 |
-
|
265 |
-
/**
|
266 |
-
* Holds the last used key
|
267 |
-
*
|
268 |
-
* @var array
|
269 |
-
* @access private
|
270 |
-
*/
|
271 |
-
var $kl;
|
272 |
-
|
273 |
-
/**
|
274 |
-
* The Key Length (in bytes)
|
275 |
-
*
|
276 |
-
* @see \phpseclib\Crypt\Base::setKeyLength()
|
277 |
-
* @var int
|
278 |
-
* @access private
|
279 |
-
* @internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16. Exists in conjunction with $Nk
|
280 |
-
* because the encryption / decryption / key schedule creation requires this number and not $key_length. We could
|
281 |
-
* derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
|
282 |
-
* of that, we'll just precompute it once.
|
283 |
-
*/
|
284 |
-
var $key_length = 16;
|
285 |
-
|
286 |
-
/**
|
287 |
-
* Sets the key length.
|
288 |
-
*
|
289 |
-
* Key lengths can be between 32 and 448 bits.
|
290 |
-
*
|
291 |
-
* @access public
|
292 |
-
* @param int $length
|
293 |
-
*/
|
294 |
-
function setKeyLength($length)
|
295 |
-
{
|
296 |
-
if ($length < 32) {
|
297 |
-
$this->key_length = 7;
|
298 |
-
} elseif ($length > 448) {
|
299 |
-
$this->key_length = 56;
|
300 |
-
} else {
|
301 |
-
$this->key_length = $length >> 3;
|
302 |
-
}
|
303 |
-
|
304 |
-
parent::setKeyLength($length);
|
305 |
-
}
|
306 |
-
|
307 |
-
/**
|
308 |
-
* Test for engine validity
|
309 |
-
*
|
310 |
-
* This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
|
311 |
-
*
|
312 |
-
* @see \phpseclib\Crypt\Base::isValidEngine()
|
313 |
-
* @param int $engine
|
314 |
-
* @access public
|
315 |
-
* @return bool
|
316 |
-
*/
|
317 |
-
function isValidEngine($engine)
|
318 |
-
{
|
319 |
-
if ($engine == self::ENGINE_OPENSSL) {
|
320 |
-
if (version_compare(PHP_VERSION, '5.3.7') < 0 && $this->key_length != 16) {
|
321 |
-
return false;
|
322 |
-
}
|
323 |
-
if ($this->key_length < 16) {
|
324 |
-
return false;
|
325 |
-
}
|
326 |
-
$this->cipher_name_openssl_ecb = 'bf-ecb';
|
327 |
-
$this->cipher_name_openssl = 'bf-' . $this->_openssl_translate_mode();
|
328 |
-
}
|
329 |
-
|
330 |
-
return parent::isValidEngine($engine);
|
331 |
-
}
|
332 |
-
|
333 |
-
/**
|
334 |
-
* Setup the key (expansion)
|
335 |
-
*
|
336 |
-
* @see \phpseclib\Crypt\Base::_setupKey()
|
337 |
-
* @access private
|
338 |
-
*/
|
339 |
-
function _setupKey()
|
340 |
-
{
|
341 |
-
if (isset($this->kl['key']) && $this->key === $this->kl['key']) {
|
342 |
-
// already expanded
|
343 |
-
return;
|
344 |
-
}
|
345 |
-
$this->kl = array('key' => $this->key);
|
346 |
-
|
347 |
-
/* key-expanding p[] and S-Box building sb[] */
|
348 |
-
$this->bctx = array(
|
349 |
-
'p' => array(),
|
350 |
-
'sb' => array(
|
351 |
-
$this->sbox0,
|
352 |
-
$this->sbox1,
|
353 |
-
$this->sbox2,
|
354 |
-
$this->sbox3
|
355 |
-
)
|
356 |
-
);
|
357 |
-
|
358 |
-
// unpack binary string in unsigned chars
|
359 |
-
$key = array_values(unpack('C*', $this->key));
|
360 |
-
$keyl = count($key);
|
361 |
-
for ($j = 0, $i = 0; $i < 18; ++$i) {
|
362 |
-
// xor P1 with the first 32-bits of the key, xor P2 with the second 32-bits ...
|
363 |
-
for ($data = 0, $k = 0; $k < 4; ++$k) {
|
364 |
-
$data = ($data << 8) | $key[$j];
|
365 |
-
if (++$j >= $keyl) {
|
366 |
-
$j = 0;
|
367 |
-
}
|
368 |
-
}
|
369 |
-
$this->bctx['p'][] = $this->parray[$i] ^ $data;
|
370 |
-
}
|
371 |
-
|
372 |
-
// encrypt the zero-string, replace P1 and P2 with the encrypted data,
|
373 |
-
// encrypt P3 and P4 with the new P1 and P2, do it with all P-array and subkeys
|
374 |
-
$data = "\0\0\0\0\0\0\0\0";
|
375 |
-
for ($i = 0; $i < 18; $i += 2) {
|
376 |
-
list($l, $r) = array_values(unpack('N*', $data = $this->_encryptBlock($data)));
|
377 |
-
$this->bctx['p'][$i ] = $l;
|
378 |
-
$this->bctx['p'][$i + 1] = $r;
|
379 |
-
}
|
380 |
-
for ($i = 0; $i < 4; ++$i) {
|
381 |
-
for ($j = 0; $j < 256; $j += 2) {
|
382 |
-
list($l, $r) = array_values(unpack('N*', $data = $this->_encryptBlock($data)));
|
383 |
-
$this->bctx['sb'][$i][$j ] = $l;
|
384 |
-
$this->bctx['sb'][$i][$j + 1] = $r;
|
385 |
-
}
|
386 |
-
}
|
387 |
-
}
|
388 |
-
|
389 |
-
/**
|
390 |
-
* Encrypts a block
|
391 |
-
*
|
392 |
-
* @access private
|
393 |
-
* @param string $in
|
394 |
-
* @return string
|
395 |
-
*/
|
396 |
-
function _encryptBlock($in)
|
397 |
-
{
|
398 |
-
$p = $this->bctx["p"];
|
399 |
-
// extract($this->bctx["sb"], EXTR_PREFIX_ALL, "sb"); // slower
|
400 |
-
$sb_0 = $this->bctx["sb"][0];
|
401 |
-
$sb_1 = $this->bctx["sb"][1];
|
402 |
-
$sb_2 = $this->bctx["sb"][2];
|
403 |
-
$sb_3 = $this->bctx["sb"][3];
|
404 |
-
|
405 |
-
$in = unpack("N*", $in);
|
406 |
-
$l = $in[1];
|
407 |
-
$r = $in[2];
|
408 |
-
|
409 |
-
for ($i = 0; $i < 16; $i+= 2) {
|
410 |
-
$l^= $p[$i];
|
411 |
-
$r^= ($sb_0[$l >> 24 & 0xff] +
|
412 |
-
$sb_1[$l >> 16 & 0xff] ^
|
413 |
-
$sb_2[$l >> 8 & 0xff]) +
|
414 |
-
$sb_3[$l & 0xff];
|
415 |
-
|
416 |
-
$r^= $p[$i + 1];
|
417 |
-
$l^= ($sb_0[$r >> 24 & 0xff] +
|
418 |
-
$sb_1[$r >> 16 & 0xff] ^
|
419 |
-
$sb_2[$r >> 8 & 0xff]) +
|
420 |
-
$sb_3[$r & 0xff];
|
421 |
-
}
|
422 |
-
return pack("N*", $r ^ $p[17], $l ^ $p[16]);
|
423 |
-
}
|
424 |
-
|
425 |
-
/**
|
426 |
-
* Decrypts a block
|
427 |
-
*
|
428 |
-
* @access private
|
429 |
-
* @param string $in
|
430 |
-
* @return string
|
431 |
-
*/
|
432 |
-
function _decryptBlock($in)
|
433 |
-
{
|
434 |
-
$p = $this->bctx["p"];
|
435 |
-
$sb_0 = $this->bctx["sb"][0];
|
436 |
-
$sb_1 = $this->bctx["sb"][1];
|
437 |
-
$sb_2 = $this->bctx["sb"][2];
|
438 |
-
$sb_3 = $this->bctx["sb"][3];
|
439 |
-
|
440 |
-
$in = unpack("N*", $in);
|
441 |
-
$l = $in[1];
|
442 |
-
$r = $in[2];
|
443 |
-
|
444 |
-
for ($i = 17; $i > 2; $i-= 2) {
|
445 |
-
$l^= $p[$i];
|
446 |
-
$r^= ($sb_0[$l >> 24 & 0xff] +
|
447 |
-
$sb_1[$l >> 16 & 0xff] ^
|
448 |
-
$sb_2[$l >> 8 & 0xff]) +
|
449 |
-
$sb_3[$l & 0xff];
|
450 |
-
|
451 |
-
$r^= $p[$i - 1];
|
452 |
-
$l^= ($sb_0[$r >> 24 & 0xff] +
|
453 |
-
$sb_1[$r >> 16 & 0xff] ^
|
454 |
-
$sb_2[$r >> 8 & 0xff]) +
|
455 |
-
$sb_3[$r & 0xff];
|
456 |
-
}
|
457 |
-
return pack("N*", $r ^ $p[0], $l ^ $p[1]);
|
458 |
-
}
|
459 |
-
|
460 |
-
/**
|
461 |
-
* Setup the performance-optimized function for de/encrypt()
|
462 |
-
*
|
463 |
-
* @see \phpseclib\Crypt\Base::_setupInlineCrypt()
|
464 |
-
* @access private
|
465 |
-
*/
|
466 |
-
function _setupInlineCrypt()
|
467 |
-
{
|
468 |
-
$lambda_functions =& self::_getLambdaFunctions();
|
469 |
-
|
470 |
-
// We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
|
471 |
-
// (Currently, for Blowfish, one generated $lambda_function cost on php5.5@32bit ~100kb unfreeable mem and ~180kb on php5.5@64bit)
|
472 |
-
// After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one.
|
473 |
-
$gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
|
474 |
-
|
475 |
-
// Generation of a unique hash for our generated code
|
476 |
-
$code_hash = "Crypt_Blowfish, {$this->mode}";
|
477 |
-
if ($gen_hi_opt_code) {
|
478 |
-
$code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
|
479 |
-
}
|
480 |
-
|
481 |
-
if (!isset($lambda_functions[$code_hash])) {
|
482 |
-
switch (true) {
|
483 |
-
case $gen_hi_opt_code:
|
484 |
-
$p = $this->bctx['p'];
|
485 |
-
$init_crypt = '
|
486 |
-
static $sb_0, $sb_1, $sb_2, $sb_3;
|
487 |
-
if (!$sb_0) {
|
488 |
-
$sb_0 = $self->bctx["sb"][0];
|
489 |
-
$sb_1 = $self->bctx["sb"][1];
|
490 |
-
$sb_2 = $self->bctx["sb"][2];
|
491 |
-
$sb_3 = $self->bctx["sb"][3];
|
492 |
-
}
|
493 |
-
';
|
494 |
-
break;
|
495 |
-
default:
|
496 |
-
$p = array();
|
497 |
-
for ($i = 0; $i < 18; ++$i) {
|
498 |
-
$p[] = '$p_' . $i;
|
499 |
-
}
|
500 |
-
$init_crypt = '
|
501 |
-
list($sb_0, $sb_1, $sb_2, $sb_3) = $self->bctx["sb"];
|
502 |
-
list(' . implode(',', $p) . ') = $self->bctx["p"];
|
503 |
-
|
504 |
-
';
|
505 |
-
}
|
506 |
-
|
507 |
-
// Generating encrypt code:
|
508 |
-
$encrypt_block = '
|
509 |
-
$in = unpack("N*", $in);
|
510 |
-
$l = $in[1];
|
511 |
-
$r = $in[2];
|
512 |
-
';
|
513 |
-
for ($i = 0; $i < 16; $i+= 2) {
|
514 |
-
$encrypt_block.= '
|
515 |
-
$l^= ' . $p[$i] . ';
|
516 |
-
$r^= ($sb_0[$l >> 24 & 0xff] +
|
517 |
-
$sb_1[$l >> 16 & 0xff] ^
|
518 |
-
$sb_2[$l >> 8 & 0xff]) +
|
519 |
-
$sb_3[$l & 0xff];
|
520 |
-
|
521 |
-
$r^= ' . $p[$i + 1] . ';
|
522 |
-
$l^= ($sb_0[$r >> 24 & 0xff] +
|
523 |
-
$sb_1[$r >> 16 & 0xff] ^
|
524 |
-
$sb_2[$r >> 8 & 0xff]) +
|
525 |
-
$sb_3[$r & 0xff];
|
526 |
-
';
|
527 |
-
}
|
528 |
-
$encrypt_block.= '
|
529 |
-
$in = pack("N*",
|
530 |
-
$r ^ ' . $p[17] . ',
|
531 |
-
$l ^ ' . $p[16] . '
|
532 |
-
);
|
533 |
-
';
|
534 |
-
|
535 |
-
// Generating decrypt code:
|
536 |
-
$decrypt_block = '
|
537 |
-
$in = unpack("N*", $in);
|
538 |
-
$l = $in[1];
|
539 |
-
$r = $in[2];
|
540 |
-
';
|
541 |
-
|
542 |
-
for ($i = 17; $i > 2; $i-= 2) {
|
543 |
-
$decrypt_block.= '
|
544 |
-
$l^= ' . $p[$i] . ';
|
545 |
-
$r^= ($sb_0[$l >> 24 & 0xff] +
|
546 |
-
$sb_1[$l >> 16 & 0xff] ^
|
547 |
-
$sb_2[$l >> 8 & 0xff]) +
|
548 |
-
$sb_3[$l & 0xff];
|
549 |
-
|
550 |
-
$r^= ' . $p[$i - 1] . ';
|
551 |
-
$l^= ($sb_0[$r >> 24 & 0xff] +
|
552 |
-
$sb_1[$r >> 16 & 0xff] ^
|
553 |
-
$sb_2[$r >> 8 & 0xff]) +
|
554 |
-
$sb_3[$r & 0xff];
|
555 |
-
';
|
556 |
-
}
|
557 |
-
|
558 |
-
$decrypt_block.= '
|
559 |
-
$in = pack("N*",
|
560 |
-
$r ^ ' . $p[0] . ',
|
561 |
-
$l ^ ' . $p[1] . '
|
562 |
-
);
|
563 |
-
';
|
564 |
-
|
565 |
-
$lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
|
566 |
-
array(
|
567 |
-
'init_crypt' => $init_crypt,
|
568 |
-
'init_encrypt' => '',
|
569 |
-
'init_decrypt' => '',
|
570 |
-
'encrypt_block' => $encrypt_block,
|
571 |
-
'decrypt_block' => $decrypt_block
|
572 |
-
)
|
573 |
-
);
|
574 |
-
}
|
575 |
-
$this->inline_crypt = $lambda_functions[$code_hash];
|
576 |
-
}
|
577 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/phpseclib/phpseclib/phpseclib/Crypt/DES.php
DELETED
@@ -1,1443 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Pure-PHP implementation of DES.
|
5 |
-
*
|
6 |
-
* Uses mcrypt, if available, and an internal implementation, otherwise.
|
7 |
-
*
|
8 |
-
* PHP version 5
|
9 |
-
*
|
10 |
-
* Useful resources are as follows:
|
11 |
-
*
|
12 |
-
* - {@link http://en.wikipedia.org/wiki/DES_supplementary_material Wikipedia: DES supplementary material}
|
13 |
-
* - {@link http://www.itl.nist.gov/fipspubs/fip46-2.htm FIPS 46-2 - (DES), Data Encryption Standard}
|
14 |
-
* - {@link http://www.cs.eku.edu/faculty/styer/460/Encrypt/JS-DES.html JavaScript DES Example}
|
15 |
-
*
|
16 |
-
* Here's a short example of how to use this library:
|
17 |
-
* <code>
|
18 |
-
* <?php
|
19 |
-
* include 'vendor/autoload.php';
|
20 |
-
*
|
21 |
-
* $des = new \phpseclib\Crypt\DES();
|
22 |
-
*
|
23 |
-
* $des->setKey('abcdefgh');
|
24 |
-
*
|
25 |
-
* $size = 10 * 1024;
|
26 |
-
* $plaintext = '';
|
27 |
-
* for ($i = 0; $i < $size; $i++) {
|
28 |
-
* $plaintext.= 'a';
|
29 |
-
* }
|
30 |
-
*
|
31 |
-
* echo $des->decrypt($des->encrypt($plaintext));
|
32 |
-
* ?>
|
33 |
-
* </code>
|
34 |
-
*
|
35 |
-
* @category Crypt
|
36 |
-
* @package DES
|
37 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
38 |
-
* @copyright 2007 Jim Wigginton
|
39 |
-
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
40 |
-
* @link http://phpseclib.sourceforge.net
|
41 |
-
*/
|
42 |
-
|
43 |
-
namespace phpseclib\Crypt;
|
44 |
-
|
45 |
-
/**
|
46 |
-
* Pure-PHP implementation of DES.
|
47 |
-
*
|
48 |
-
* @package DES
|
49 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
50 |
-
* @access public
|
51 |
-
*/
|
52 |
-
class DES extends Base
|
53 |
-
{
|
54 |
-
/**#@+
|
55 |
-
* @access private
|
56 |
-
* @see \phpseclib\Crypt\DES::_setupKey()
|
57 |
-
* @see \phpseclib\Crypt\DES::_processBlock()
|
58 |
-
*/
|
59 |
-
/**
|
60 |
-
* Contains $keys[self::ENCRYPT]
|
61 |
-
*/
|
62 |
-
const ENCRYPT = 0;
|
63 |
-
/**
|
64 |
-
* Contains $keys[self::DECRYPT]
|
65 |
-
*/
|
66 |
-
const DECRYPT = 1;
|
67 |
-
/**#@-*/
|
68 |
-
|
69 |
-
/**
|
70 |
-
* Block Length of the cipher
|
71 |
-
*
|
72 |
-
* @see \phpseclib\Crypt\Base::block_size
|
73 |
-
* @var int
|
74 |
-
* @access private
|
75 |
-
*/
|
76 |
-
var $block_size = 8;
|
77 |
-
|
78 |
-
/**
|
79 |
-
* Key Length (in bytes)
|
80 |
-
*
|
81 |
-
* @see \phpseclib\Crypt\Base::setKeyLength()
|
82 |
-
* @var int
|
83 |
-
* @access private
|
84 |
-
*/
|
85 |
-
var $key_length = 8;
|
86 |
-
|
87 |
-
/**
|
88 |
-
* The mcrypt specific name of the cipher
|
89 |
-
*
|
90 |
-
* @see \phpseclib\Crypt\Base::cipher_name_mcrypt
|
91 |
-
* @var string
|
92 |
-
* @access private
|
93 |
-
*/
|
94 |
-
var $cipher_name_mcrypt = 'des';
|
95 |
-
|
96 |
-
/**
|
97 |
-
* The OpenSSL names of the cipher / modes
|
98 |
-
*
|
99 |
-
* @see \phpseclib\Crypt\Base::openssl_mode_names
|
100 |
-
* @var array
|
101 |
-
* @access private
|
102 |
-
*/
|
103 |
-
var $openssl_mode_names = array(
|
104 |
-
self::MODE_ECB => 'des-ecb',
|
105 |
-
self::MODE_CBC => 'des-cbc',
|
106 |
-
self::MODE_CFB => 'des-cfb',
|
107 |
-
self::MODE_OFB => 'des-ofb'
|
108 |
-
// self::MODE_CTR is undefined for DES
|
109 |
-
);
|
110 |
-
|
111 |
-
/**
|
112 |
-
* Optimizing value while CFB-encrypting
|
113 |
-
*
|
114 |
-
* @see \phpseclib\Crypt\Base::cfb_init_len
|
115 |
-
* @var int
|
116 |
-
* @access private
|
117 |
-
*/
|
118 |
-
var $cfb_init_len = 500;
|
119 |
-
|
120 |
-
/**
|
121 |
-
* Switch for DES/3DES encryption
|
122 |
-
*
|
123 |
-
* Used only if $engine == self::ENGINE_INTERNAL
|
124 |
-
*
|
125 |
-
* @see self::_setupKey()
|
126 |
-
* @see self::_processBlock()
|
127 |
-
* @var int
|
128 |
-
* @access private
|
129 |
-
*/
|
130 |
-
var $des_rounds = 1;
|
131 |
-
|
132 |
-
/**
|
133 |
-
* max possible size of $key
|
134 |
-
*
|
135 |
-
* @see self::setKey()
|
136 |
-
* @var string
|
137 |
-
* @access private
|
138 |
-
*/
|
139 |
-
var $key_length_max = 8;
|
140 |
-
|
141 |
-
/**
|
142 |
-
* The Key Schedule
|
143 |
-
*
|
144 |
-
* @see self::_setupKey()
|
145 |
-
* @var array
|
146 |
-
* @access private
|
147 |
-
*/
|
148 |
-
var $keys;
|
149 |
-
|
150 |
-
/**
|
151 |
-
* Shuffle table.
|
152 |
-
*
|
153 |
-
* For each byte value index, the entry holds an 8-byte string
|
154 |
-
* with each byte containing all bits in the same state as the
|
155 |
-
* corresponding bit in the index value.
|
156 |
-
*
|
157 |
-
* @see self::_processBlock()
|
158 |
-
* @see self::_setupKey()
|
159 |
-
* @var array
|
160 |
-
* @access private
|
161 |
-
*/
|
162 |
-
var $shuffle = array(
|
163 |
-
"\x00\x00\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00\x00\x00\x00\xFF",
|
164 |
-
"\x00\x00\x00\x00\x00\x00\xFF\x00", "\x00\x00\x00\x00\x00\x00\xFF\xFF",
|
165 |
-
"\x00\x00\x00\x00\x00\xFF\x00\x00", "\x00\x00\x00\x00\x00\xFF\x00\xFF",
|
166 |
-
"\x00\x00\x00\x00\x00\xFF\xFF\x00", "\x00\x00\x00\x00\x00\xFF\xFF\xFF",
|
167 |
-
"\x00\x00\x00\x00\xFF\x00\x00\x00", "\x00\x00\x00\x00\xFF\x00\x00\xFF",
|
168 |
-
"\x00\x00\x00\x00\xFF\x00\xFF\x00", "\x00\x00\x00\x00\xFF\x00\xFF\xFF",
|
169 |
-
"\x00\x00\x00\x00\xFF\xFF\x00\x00", "\x00\x00\x00\x00\xFF\xFF\x00\xFF",
|
170 |
-
"\x00\x00\x00\x00\xFF\xFF\xFF\x00", "\x00\x00\x00\x00\xFF\xFF\xFF\xFF",
|
171 |
-
"\x00\x00\x00\xFF\x00\x00\x00\x00", "\x00\x00\x00\xFF\x00\x00\x00\xFF",
|
172 |
-
"\x00\x00\x00\xFF\x00\x00\xFF\x00", "\x00\x00\x00\xFF\x00\x00\xFF\xFF",
|
173 |
-
"\x00\x00\x00\xFF\x00\xFF\x00\x00", "\x00\x00\x00\xFF\x00\xFF\x00\xFF",
|
174 |
-
"\x00\x00\x00\xFF\x00\xFF\xFF\x00", "\x00\x00\x00\xFF\x00\xFF\xFF\xFF",
|
175 |
-
"\x00\x00\x00\xFF\xFF\x00\x00\x00", "\x00\x00\x00\xFF\xFF\x00\x00\xFF",
|
176 |
-
"\x00\x00\x00\xFF\xFF\x00\xFF\x00", "\x00\x00\x00\xFF\xFF\x00\xFF\xFF",
|
177 |
-
"\x00\x00\x00\xFF\xFF\xFF\x00\x00", "\x00\x00\x00\xFF\xFF\xFF\x00\xFF",
|
178 |
-
"\x00\x00\x00\xFF\xFF\xFF\xFF\x00", "\x00\x00\x00\xFF\xFF\xFF\xFF\xFF",
|
179 |
-
"\x00\x00\xFF\x00\x00\x00\x00\x00", "\x00\x00\xFF\x00\x00\x00\x00\xFF",
|
180 |
-
"\x00\x00\xFF\x00\x00\x00\xFF\x00", "\x00\x00\xFF\x00\x00\x00\xFF\xFF",
|
181 |
-
"\x00\x00\xFF\x00\x00\xFF\x00\x00", "\x00\x00\xFF\x00\x00\xFF\x00\xFF",
|
182 |
-
"\x00\x00\xFF\x00\x00\xFF\xFF\x00", "\x00\x00\xFF\x00\x00\xFF\xFF\xFF",
|
183 |
-
"\x00\x00\xFF\x00\xFF\x00\x00\x00", "\x00\x00\xFF\x00\xFF\x00\x00\xFF",
|
184 |
-
"\x00\x00\xFF\x00\xFF\x00\xFF\x00", "\x00\x00\xFF\x00\xFF\x00\xFF\xFF",
|
185 |
-
"\x00\x00\xFF\x00\xFF\xFF\x00\x00", "\x00\x00\xFF\x00\xFF\xFF\x00\xFF",
|
186 |
-
"\x00\x00\xFF\x00\xFF\xFF\xFF\x00", "\x00\x00\xFF\x00\xFF\xFF\xFF\xFF",
|
187 |
-
"\x00\x00\xFF\xFF\x00\x00\x00\x00", "\x00\x00\xFF\xFF\x00\x00\x00\xFF",
|
188 |
-
"\x00\x00\xFF\xFF\x00\x00\xFF\x00", "\x00\x00\xFF\xFF\x00\x00\xFF\xFF",
|
189 |
-
"\x00\x00\xFF\xFF\x00\xFF\x00\x00", "\x00\x00\xFF\xFF\x00\xFF\x00\xFF",
|
190 |
-
"\x00\x00\xFF\xFF\x00\xFF\xFF\x00", "\x00\x00\xFF\xFF\x00\xFF\xFF\xFF",
|
191 |
-
"\x00\x00\xFF\xFF\xFF\x00\x00\x00", "\x00\x00\xFF\xFF\xFF\x00\x00\xFF",
|
192 |
-
"\x00\x00\xFF\xFF\xFF\x00\xFF\x00", "\x00\x00\xFF\xFF\xFF\x00\xFF\xFF",
|
193 |
-
"\x00\x00\xFF\xFF\xFF\xFF\x00\x00", "\x00\x00\xFF\xFF\xFF\xFF\x00\xFF",
|
194 |
-
"\x00\x00\xFF\xFF\xFF\xFF\xFF\x00", "\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF",
|
195 |
-
"\x00\xFF\x00\x00\x00\x00\x00\x00", "\x00\xFF\x00\x00\x00\x00\x00\xFF",
|
196 |
-
"\x00\xFF\x00\x00\x00\x00\xFF\x00", "\x00\xFF\x00\x00\x00\x00\xFF\xFF",
|
197 |
-
"\x00\xFF\x00\x00\x00\xFF\x00\x00", "\x00\xFF\x00\x00\x00\xFF\x00\xFF",
|
198 |
-
"\x00\xFF\x00\x00\x00\xFF\xFF\x00", "\x00\xFF\x00\x00\x00\xFF\xFF\xFF",
|
199 |
-
"\x00\xFF\x00\x00\xFF\x00\x00\x00", "\x00\xFF\x00\x00\xFF\x00\x00\xFF",
|
200 |
-
"\x00\xFF\x00\x00\xFF\x00\xFF\x00", "\x00\xFF\x00\x00\xFF\x00\xFF\xFF",
|
201 |
-
"\x00\xFF\x00\x00\xFF\xFF\x00\x00", "\x00\xFF\x00\x00\xFF\xFF\x00\xFF",
|
202 |
-
"\x00\xFF\x00\x00\xFF\xFF\xFF\x00", "\x00\xFF\x00\x00\xFF\xFF\xFF\xFF",
|
203 |
-
"\x00\xFF\x00\xFF\x00\x00\x00\x00", "\x00\xFF\x00\xFF\x00\x00\x00\xFF",
|
204 |
-
"\x00\xFF\x00\xFF\x00\x00\xFF\x00", "\x00\xFF\x00\xFF\x00\x00\xFF\xFF",
|
205 |
-
"\x00\xFF\x00\xFF\x00\xFF\x00\x00", "\x00\xFF\x00\xFF\x00\xFF\x00\xFF",
|
206 |
-
"\x00\xFF\x00\xFF\x00\xFF\xFF\x00", "\x00\xFF\x00\xFF\x00\xFF\xFF\xFF",
|
207 |
-
"\x00\xFF\x00\xFF\xFF\x00\x00\x00", "\x00\xFF\x00\xFF\xFF\x00\x00\xFF",
|
208 |
-
"\x00\xFF\x00\xFF\xFF\x00\xFF\x00", "\x00\xFF\x00\xFF\xFF\x00\xFF\xFF",
|
209 |
-
"\x00\xFF\x00\xFF\xFF\xFF\x00\x00", "\x00\xFF\x00\xFF\xFF\xFF\x00\xFF",
|
210 |
-
"\x00\xFF\x00\xFF\xFF\xFF\xFF\x00", "\x00\xFF\x00\xFF\xFF\xFF\xFF\xFF",
|
211 |
-
"\x00\xFF\xFF\x00\x00\x00\x00\x00", "\x00\xFF\xFF\x00\x00\x00\x00\xFF",
|
212 |
-
"\x00\xFF\xFF\x00\x00\x00\xFF\x00", "\x00\xFF\xFF\x00\x00\x00\xFF\xFF",
|
213 |
-
"\x00\xFF\xFF\x00\x00\xFF\x00\x00", "\x00\xFF\xFF\x00\x00\xFF\x00\xFF",
|
214 |
-
"\x00\xFF\xFF\x00\x00\xFF\xFF\x00", "\x00\xFF\xFF\x00\x00\xFF\xFF\xFF",
|
215 |
-
"\x00\xFF\xFF\x00\xFF\x00\x00\x00", "\x00\xFF\xFF\x00\xFF\x00\x00\xFF",
|
216 |
-
"\x00\xFF\xFF\x00\xFF\x00\xFF\x00", "\x00\xFF\xFF\x00\xFF\x00\xFF\xFF",
|
217 |
-
"\x00\xFF\xFF\x00\xFF\xFF\x00\x00", "\x00\xFF\xFF\x00\xFF\xFF\x00\xFF",
|
218 |
-
"\x00\xFF\xFF\x00\xFF\xFF\xFF\x00", "\x00\xFF\xFF\x00\xFF\xFF\xFF\xFF",
|
219 |
-
"\x00\xFF\xFF\xFF\x00\x00\x00\x00", "\x00\xFF\xFF\xFF\x00\x00\x00\xFF",
|
220 |
-
"\x00\xFF\xFF\xFF\x00\x00\xFF\x00", "\x00\xFF\xFF\xFF\x00\x00\xFF\xFF",
|
221 |
-
"\x00\xFF\xFF\xFF\x00\xFF\x00\x00", "\x00\xFF\xFF\xFF\x00\xFF\x00\xFF",
|
222 |
-
"\x00\xFF\xFF\xFF\x00\xFF\xFF\x00", "\x00\xFF\xFF\xFF\x00\xFF\xFF\xFF",
|
223 |
-
"\x00\xFF\xFF\xFF\xFF\x00\x00\x00", "\x00\xFF\xFF\xFF\xFF\x00\x00\xFF",
|
224 |
-
"\x00\xFF\xFF\xFF\xFF\x00\xFF\x00", "\x00\xFF\xFF\xFF\xFF\x00\xFF\xFF",
|
225 |
-
"\x00\xFF\xFF\xFF\xFF\xFF\x00\x00", "\x00\xFF\xFF\xFF\xFF\xFF\x00\xFF",
|
226 |
-
"\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00", "\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
|
227 |
-
"\xFF\x00\x00\x00\x00\x00\x00\x00", "\xFF\x00\x00\x00\x00\x00\x00\xFF",
|
228 |
-
"\xFF\x00\x00\x00\x00\x00\xFF\x00", "\xFF\x00\x00\x00\x00\x00\xFF\xFF",
|
229 |
-
"\xFF\x00\x00\x00\x00\xFF\x00\x00", "\xFF\x00\x00\x00\x00\xFF\x00\xFF",
|
230 |
-
"\xFF\x00\x00\x00\x00\xFF\xFF\x00", "\xFF\x00\x00\x00\x00\xFF\xFF\xFF",
|
231 |
-
"\xFF\x00\x00\x00\xFF\x00\x00\x00", "\xFF\x00\x00\x00\xFF\x00\x00\xFF",
|
232 |
-
"\xFF\x00\x00\x00\xFF\x00\xFF\x00", "\xFF\x00\x00\x00\xFF\x00\xFF\xFF",
|
233 |
-
"\xFF\x00\x00\x00\xFF\xFF\x00\x00", "\xFF\x00\x00\x00\xFF\xFF\x00\xFF",
|
234 |
-
"\xFF\x00\x00\x00\xFF\xFF\xFF\x00", "\xFF\x00\x00\x00\xFF\xFF\xFF\xFF",
|
235 |
-
"\xFF\x00\x00\xFF\x00\x00\x00\x00", "\xFF\x00\x00\xFF\x00\x00\x00\xFF",
|
236 |
-
"\xFF\x00\x00\xFF\x00\x00\xFF\x00", "\xFF\x00\x00\xFF\x00\x00\xFF\xFF",
|
237 |
-
"\xFF\x00\x00\xFF\x00\xFF\x00\x00", "\xFF\x00\x00\xFF\x00\xFF\x00\xFF",
|
238 |
-
"\xFF\x00\x00\xFF\x00\xFF\xFF\x00", "\xFF\x00\x00\xFF\x00\xFF\xFF\xFF",
|
239 |
-
"\xFF\x00\x00\xFF\xFF\x00\x00\x00", "\xFF\x00\x00\xFF\xFF\x00\x00\xFF",
|
240 |
-
"\xFF\x00\x00\xFF\xFF\x00\xFF\x00", "\xFF\x00\x00\xFF\xFF\x00\xFF\xFF",
|
241 |
-
"\xFF\x00\x00\xFF\xFF\xFF\x00\x00", "\xFF\x00\x00\xFF\xFF\xFF\x00\xFF",
|
242 |
-
"\xFF\x00\x00\xFF\xFF\xFF\xFF\x00", "\xFF\x00\x00\xFF\xFF\xFF\xFF\xFF",
|
243 |
-
"\xFF\x00\xFF\x00\x00\x00\x00\x00", "\xFF\x00\xFF\x00\x00\x00\x00\xFF",
|
244 |
-
"\xFF\x00\xFF\x00\x00\x00\xFF\x00", "\xFF\x00\xFF\x00\x00\x00\xFF\xFF",
|
245 |
-
"\xFF\x00\xFF\x00\x00\xFF\x00\x00", "\xFF\x00\xFF\x00\x00\xFF\x00\xFF",
|
246 |
-
"\xFF\x00\xFF\x00\x00\xFF\xFF\x00", "\xFF\x00\xFF\x00\x00\xFF\xFF\xFF",
|
247 |
-
"\xFF\x00\xFF\x00\xFF\x00\x00\x00", "\xFF\x00\xFF\x00\xFF\x00\x00\xFF",
|
248 |
-
"\xFF\x00\xFF\x00\xFF\x00\xFF\x00", "\xFF\x00\xFF\x00\xFF\x00\xFF\xFF",
|
249 |
-
"\xFF\x00\xFF\x00\xFF\xFF\x00\x00", "\xFF\x00\xFF\x00\xFF\xFF\x00\xFF",
|
250 |
-
"\xFF\x00\xFF\x00\xFF\xFF\xFF\x00", "\xFF\x00\xFF\x00\xFF\xFF\xFF\xFF",
|
251 |
-
"\xFF\x00\xFF\xFF\x00\x00\x00\x00", "\xFF\x00\xFF\xFF\x00\x00\x00\xFF",
|
252 |
-
"\xFF\x00\xFF\xFF\x00\x00\xFF\x00", "\xFF\x00\xFF\xFF\x00\x00\xFF\xFF",
|
253 |
-
"\xFF\x00\xFF\xFF\x00\xFF\x00\x00", "\xFF\x00\xFF\xFF\x00\xFF\x00\xFF",
|
254 |
-
"\xFF\x00\xFF\xFF\x00\xFF\xFF\x00", "\xFF\x00\xFF\xFF\x00\xFF\xFF\xFF",
|
255 |
-
"\xFF\x00\xFF\xFF\xFF\x00\x00\x00", "\xFF\x00\xFF\xFF\xFF\x00\x00\xFF",
|
256 |
-
"\xFF\x00\xFF\xFF\xFF\x00\xFF\x00", "\xFF\x00\xFF\xFF\xFF\x00\xFF\xFF",
|
257 |
-
"\xFF\x00\xFF\xFF\xFF\xFF\x00\x00", "\xFF\x00\xFF\xFF\xFF\xFF\x00\xFF",
|
258 |
-
"\xFF\x00\xFF\xFF\xFF\xFF\xFF\x00", "\xFF\x00\xFF\xFF\xFF\xFF\xFF\xFF",
|
259 |
-
"\xFF\xFF\x00\x00\x00\x00\x00\x00", "\xFF\xFF\x00\x00\x00\x00\x00\xFF",
|
260 |
-
"\xFF\xFF\x00\x00\x00\x00\xFF\x00", "\xFF\xFF\x00\x00\x00\x00\xFF\xFF",
|
261 |
-
"\xFF\xFF\x00\x00\x00\xFF\x00\x00", "\xFF\xFF\x00\x00\x00\xFF\x00\xFF",
|
262 |
-
"\xFF\xFF\x00\x00\x00\xFF\xFF\x00", "\xFF\xFF\x00\x00\x00\xFF\xFF\xFF",
|
263 |
-
"\xFF\xFF\x00\x00\xFF\x00\x00\x00", "\xFF\xFF\x00\x00\xFF\x00\x00\xFF",
|
264 |
-
"\xFF\xFF\x00\x00\xFF\x00\xFF\x00", "\xFF\xFF\x00\x00\xFF\x00\xFF\xFF",
|
265 |
-
"\xFF\xFF\x00\x00\xFF\xFF\x00\x00", "\xFF\xFF\x00\x00\xFF\xFF\x00\xFF",
|
266 |
-
"\xFF\xFF\x00\x00\xFF\xFF\xFF\x00", "\xFF\xFF\x00\x00\xFF\xFF\xFF\xFF",
|
267 |
-
"\xFF\xFF\x00\xFF\x00\x00\x00\x00", "\xFF\xFF\x00\xFF\x00\x00\x00\xFF",
|
268 |
-
"\xFF\xFF\x00\xFF\x00\x00\xFF\x00", "\xFF\xFF\x00\xFF\x00\x00\xFF\xFF",
|
269 |
-
"\xFF\xFF\x00\xFF\x00\xFF\x00\x00", "\xFF\xFF\x00\xFF\x00\xFF\x00\xFF",
|
270 |
-
"\xFF\xFF\x00\xFF\x00\xFF\xFF\x00", "\xFF\xFF\x00\xFF\x00\xFF\xFF\xFF",
|
271 |
-
"\xFF\xFF\x00\xFF\xFF\x00\x00\x00", "\xFF\xFF\x00\xFF\xFF\x00\x00\xFF",
|
272 |
-
"\xFF\xFF\x00\xFF\xFF\x00\xFF\x00", "\xFF\xFF\x00\xFF\xFF\x00\xFF\xFF",
|
273 |
-
"\xFF\xFF\x00\xFF\xFF\xFF\x00\x00", "\xFF\xFF\x00\xFF\xFF\xFF\x00\xFF",
|
274 |
-
"\xFF\xFF\x00\xFF\xFF\xFF\xFF\x00", "\xFF\xFF\x00\xFF\xFF\xFF\xFF\xFF",
|
275 |
-
"\xFF\xFF\xFF\x00\x00\x00\x00\x00", "\xFF\xFF\xFF\x00\x00\x00\x00\xFF",
|
276 |
-
"\xFF\xFF\xFF\x00\x00\x00\xFF\x00", "\xFF\xFF\xFF\x00\x00\x00\xFF\xFF",
|
277 |
-
"\xFF\xFF\xFF\x00\x00\xFF\x00\x00", "\xFF\xFF\xFF\x00\x00\xFF\x00\xFF",
|
278 |
-
"\xFF\xFF\xFF\x00\x00\xFF\xFF\x00", "\xFF\xFF\xFF\x00\x00\xFF\xFF\xFF",
|
279 |
-
"\xFF\xFF\xFF\x00\xFF\x00\x00\x00", "\xFF\xFF\xFF\x00\xFF\x00\x00\xFF",
|
280 |
-
"\xFF\xFF\xFF\x00\xFF\x00\xFF\x00", "\xFF\xFF\xFF\x00\xFF\x00\xFF\xFF",
|
281 |
-
"\xFF\xFF\xFF\x00\xFF\xFF\x00\x00", "\xFF\xFF\xFF\x00\xFF\xFF\x00\xFF",
|
282 |
-
"\xFF\xFF\xFF\x00\xFF\xFF\xFF\x00", "\xFF\xFF\xFF\x00\xFF\xFF\xFF\xFF",
|
283 |
-
"\xFF\xFF\xFF\xFF\x00\x00\x00\x00", "\xFF\xFF\xFF\xFF\x00\x00\x00\xFF",
|
284 |
-
"\xFF\xFF\xFF\xFF\x00\x00\xFF\x00", "\xFF\xFF\xFF\xFF\x00\x00\xFF\xFF",
|
285 |
-
"\xFF\xFF\xFF\xFF\x00\xFF\x00\x00", "\xFF\xFF\xFF\xFF\x00\xFF\x00\xFF",
|
286 |
-
"\xFF\xFF\xFF\xFF\x00\xFF\xFF\x00", "\xFF\xFF\xFF\xFF\x00\xFF\xFF\xFF",
|
287 |
-
"\xFF\xFF\xFF\xFF\xFF\x00\x00\x00", "\xFF\xFF\xFF\xFF\xFF\x00\x00\xFF",
|
288 |
-
"\xFF\xFF\xFF\xFF\xFF\x00\xFF\x00", "\xFF\xFF\xFF\xFF\xFF\x00\xFF\xFF",
|
289 |
-
"\xFF\xFF\xFF\xFF\xFF\xFF\x00\x00", "\xFF\xFF\xFF\xFF\xFF\xFF\x00\xFF",
|
290 |
-
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x00", "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
|
291 |
-
);
|
292 |
-
|
293 |
-
/**
|
294 |
-
* IP mapping helper table.
|
295 |
-
*
|
296 |
-
* Indexing this table with each source byte performs the initial bit permutation.
|
297 |
-
*
|
298 |
-
* @var array
|
299 |
-
* @access private
|
300 |
-
*/
|
301 |
-
var $ipmap = array(
|
302 |
-
0x00, 0x10, 0x01, 0x11, 0x20, 0x30, 0x21, 0x31,
|
303 |
-
0x02, 0x12, 0x03, 0x13, 0x22, 0x32, 0x23, 0x33,
|
304 |
-
0x40, 0x50, 0x41, 0x51, 0x60, 0x70, 0x61, 0x71,
|
305 |
-
0x42, 0x52, 0x43, 0x53, 0x62, 0x72, 0x63, 0x73,
|
306 |
-
0x04, 0x14, 0x05, 0x15, 0x24, 0x34, 0x25, 0x35,
|
307 |
-
0x06, 0x16, 0x07, 0x17, 0x26, 0x36, 0x27, 0x37,
|
308 |
-
0x44, 0x54, 0x45, 0x55, 0x64, 0x74, 0x65, 0x75,
|
309 |
-
0x46, 0x56, 0x47, 0x57, 0x66, 0x76, 0x67, 0x77,
|
310 |
-
0x80, 0x90, 0x81, 0x91, 0xA0, 0xB0, 0xA1, 0xB1,
|
311 |
-
0x82, 0x92, 0x83, 0x93, 0xA2, 0xB2, 0xA3, 0xB3,
|
312 |
-
0xC0, 0xD0, 0xC1, 0xD1, 0xE0, 0xF0, 0xE1, 0xF1,
|
313 |
-
0xC2, 0xD2, 0xC3, 0xD3, 0xE2, 0xF2, 0xE3, 0xF3,
|
314 |
-
0x84, 0x94, 0x85, 0x95, 0xA4, 0xB4, 0xA5, 0xB5,
|
315 |
-
0x86, 0x96, 0x87, 0x97, 0xA6, 0xB6, 0xA7, 0xB7,
|
316 |
-
0xC4, 0xD4, 0xC5, 0xD5, 0xE4, 0xF4, 0xE5, 0xF5,
|
317 |
-
0xC6, 0xD6, 0xC7, 0xD7, 0xE6, 0xF6, 0xE7, 0xF7,
|
318 |
-
0x08, 0x18, 0x09, 0x19, 0x28, 0x38, 0x29, 0x39,
|
319 |
-
0x0A, 0x1A, 0x0B, 0x1B, 0x2A, 0x3A, 0x2B, 0x3B,
|
320 |
-
0x48, 0x58, 0x49, 0x59, 0x68, 0x78, 0x69, 0x79,
|
321 |
-
0x4A, 0x5A, 0x4B, 0x5B, 0x6A, 0x7A, 0x6B, 0x7B,
|
322 |
-
0x0C, 0x1C, 0x0D, 0x1D, 0x2C, 0x3C, 0x2D, 0x3D,
|
323 |
-
0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
|
324 |
-
0x4C, 0x5C, 0x4D, 0x5D, 0x6C, 0x7C, 0x6D, 0x7D,
|
325 |
-
0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
|
326 |
-
0x88, 0x98, 0x89, 0x99, 0xA8, 0xB8, 0xA9, 0xB9,
|
327 |
-
0x8A, 0x9A, 0x8B, 0x9B, 0xAA, 0xBA, 0xAB, 0xBB,
|
328 |
-
0xC8, 0xD8, 0xC9, 0xD9, 0xE8, 0xF8, 0xE9, 0xF9,
|
329 |
-
0xCA, 0xDA, 0xCB, 0xDB, 0xEA, 0xFA, 0xEB, 0xFB,
|
330 |
-
0x8C, 0x9C, 0x8D, 0x9D, 0xAC, 0xBC, 0xAD, 0xBD,
|
331 |
-
0x8E, 0x9E, 0x8F, 0x9F, 0xAE, 0xBE, 0xAF, 0xBF,
|
332 |
-
0xCC, 0xDC, 0xCD, 0xDD, 0xEC, 0xFC, 0xED, 0xFD,
|
333 |
-
0xCE, 0xDE, 0xCF, 0xDF, 0xEE, 0xFE, 0xEF, 0xFF
|
334 |
-
);
|
335 |
-
|
336 |
-
/**
|
337 |
-
* Inverse IP mapping helper table.
|
338 |
-
* Indexing this table with a byte value reverses the bit order.
|
339 |
-
*
|
340 |
-
* @var array
|
341 |
-
* @access private
|
342 |
-
*/
|
343 |
-
var $invipmap = array(
|
344 |
-
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
|
345 |
-
0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
|
346 |
-
0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
|
347 |
-
0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
|
348 |
-
0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
|
349 |
-
0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
|
350 |
-
0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
|
351 |
-
0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
|
352 |
-
0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
|
353 |
-
0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
|
354 |
-
0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
|
355 |
-
0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
|
356 |
-
0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
|
357 |
-
0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
|
358 |
-
0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
|
359 |
-
0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
|
360 |
-
0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
|
361 |
-
0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
|
362 |
-
0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
|
363 |
-
0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
|
364 |
-
0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
|
365 |
-
0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
|
366 |
-
0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
|
367 |
-
0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
|
368 |
-
0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
|
369 |
-
0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
|
370 |
-
0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
|
371 |
-
0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
|
372 |
-
0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
|
373 |
-
0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
|
374 |
-
0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
|
375 |
-
0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
|
376 |
-
);
|
377 |
-
|
378 |
-
/**
|
379 |
-
* Pre-permuted S-box1
|
380 |
-
*
|
381 |
-
* Each box ($sbox1-$sbox8) has been vectorized, then each value pre-permuted using the
|
382 |
-
* P table: concatenation can then be replaced by exclusive ORs.
|
383 |
-
*
|
384 |
-
* @var array
|
385 |
-
* @access private
|
386 |
-
*/
|
387 |
-
var $sbox1 = array(
|
388 |
-
0x00808200, 0x00000000, 0x00008000, 0x00808202,
|
389 |
-
0x00808002, 0x00008202, 0x00000002, 0x00008000,
|
390 |
-
0x00000200, 0x00808200, 0x00808202, 0x00000200,
|
391 |
-
0x00800202, 0x00808002, 0x00800000, 0x00000002,
|
392 |
-
0x00000202, 0x00800200, 0x00800200, 0x00008200,
|
393 |
-
0x00008200, 0x00808000, 0x00808000, 0x00800202,
|
394 |
-
0x00008002, 0x00800002, 0x00800002, 0x00008002,
|
395 |
-
0x00000000, 0x00000202, 0x00008202, 0x00800000,
|
396 |
-
0x00008000, 0x00808202, 0x00000002, 0x00808000,
|
397 |
-
0x00808200, 0x00800000, 0x00800000, 0x00000200,
|
398 |
-
0x00808002, 0x00008000, 0x00008200, 0x00800002,
|
399 |
-
0x00000200, 0x00000002, 0x00800202, 0x00008202,
|
400 |
-
0x00808202, 0x00008002, 0x00808000, 0x00800202,
|
401 |
-
0x00800002, 0x00000202, 0x00008202, 0x00808200,
|
402 |
-
0x00000202, 0x00800200, 0x00800200, 0x00000000,
|
403 |
-
0x00008002, 0x00008200, 0x00000000, 0x00808002
|
404 |
-
);
|
405 |
-
|
406 |
-
/**
|
407 |
-
* Pre-permuted S-box2
|
408 |
-
*
|
409 |
-
* @var array
|
410 |
-
* @access private
|
411 |
-
*/
|
412 |
-
var $sbox2 = array(
|
413 |
-
0x40084010, 0x40004000, 0x00004000, 0x00084010,
|
414 |
-
0x00080000, 0x00000010, 0x40080010, 0x40004010,
|
415 |
-
0x40000010, 0x40084010, 0x40084000, 0x40000000,
|
416 |
-
0x40004000, 0x00080000, 0x00000010, 0x40080010,
|
417 |
-
0x00084000, 0x00080010, 0x40004010, 0x00000000,
|
418 |
-
0x40000000, 0x00004000, 0x00084010, 0x40080000,
|
419 |
-
0x00080010, 0x40000010, 0x00000000, 0x00084000,
|
420 |
-
0x00004010, 0x40084000, 0x40080000, 0x00004010,
|
421 |
-
0x00000000, 0x00084010, 0x40080010, 0x00080000,
|
422 |
-
0x40004010, 0x40080000, 0x40084000, 0x00004000,
|
423 |
-
0x40080000, 0x40004000, 0x00000010, 0x40084010,
|
424 |
-
0x00084010, 0x00000010, 0x00004000, 0x40000000,
|
425 |
-
0x00004010, 0x40084000, 0x00080000, 0x40000010,
|
426 |
-
0x00080010, 0x40004010, 0x40000010, 0x00080010,
|
427 |
-
0x00084000, 0x00000000, 0x40004000, 0x00004010,
|
428 |
-
0x40000000, 0x40080010, 0x40084010, 0x00084000
|
429 |
-
);
|
430 |
-
|
431 |
-
/**
|
432 |
-
* Pre-permuted S-box3
|
433 |
-
*
|
434 |
-
* @var array
|
435 |
-
* @access private
|
436 |
-
*/
|
437 |
-
var $sbox3 = array(
|
438 |
-
0x00000104, 0x04010100, 0x00000000, 0x04010004,
|
439 |
-
0x04000100, 0x00000000, 0x00010104, 0x04000100,
|
440 |
-
0x00010004, 0x04000004, 0x04000004, 0x00010000,
|
441 |
-
0x04010104, 0x00010004, 0x04010000, 0x00000104,
|
442 |
-
0x04000000, 0x00000004, 0x04010100, 0x00000100,
|
443 |
-
0x00010100, 0x04010000, 0x04010004, 0x00010104,
|
444 |
-
0x04000104, 0x00010100, 0x00010000, 0x04000104,
|
445 |
-
0x00000004, 0x04010104, 0x00000100, 0x04000000,
|
446 |
-
0x04010100, 0x04000000, 0x00010004, 0x00000104,
|
447 |
-
0x00010000, 0x04010100, 0x04000100, 0x00000000,
|
448 |
-
0x00000100, 0x00010004, 0x04010104, 0x04000100,
|
449 |
-
0x04000004, 0x00000100, 0x00000000, 0x04010004,
|
450 |
-
0x04000104, 0x00010000, 0x04000000, 0x04010104,
|
451 |
-
0x00000004, 0x00010104, 0x00010100, 0x04000004,
|
452 |
-
0x04010000, 0x04000104, 0x00000104, 0x04010000,
|
453 |
-
0x00010104, 0x00000004, 0x04010004, 0x00010100
|
454 |
-
);
|
455 |
-
|
456 |
-
/**
|
457 |
-
* Pre-permuted S-box4
|
458 |
-
*
|
459 |
-
* @var array
|
460 |
-
* @access private
|
461 |
-
*/
|
462 |
-
var $sbox4 = array(
|
463 |
-
0x80401000, 0x80001040, 0x80001040, 0x00000040,
|
464 |
-
0x00401040, 0x80400040, 0x80400000, 0x80001000,
|
465 |
-
0x00000000, 0x00401000, 0x00401000, 0x80401040,
|
466 |
-
0x80000040, 0x00000000, 0x00400040, 0x80400000,
|
467 |
-
0x80000000, 0x00001000, 0x00400000, 0x80401000,
|
468 |
-
0x00000040, 0x00400000, 0x80001000, 0x00001040,
|
469 |
-
0x80400040, 0x80000000, 0x00001040, 0x00400040,
|
470 |
-
0x00001000, 0x00401040, 0x80401040, 0x80000040,
|
471 |
-
0x00400040, 0x80400000, 0x00401000, 0x80401040,
|
472 |
-
0x80000040, 0x00000000, 0x00000000, 0x00401000,
|
473 |
-
0x00001040, 0x00400040, 0x80400040, 0x80000000,
|
474 |
-
0x80401000, 0x80001040, 0x80001040, 0x00000040,
|
475 |
-
0x80401040, 0x80000040, 0x80000000, 0x00001000,
|
476 |
-
0x80400000, 0x80001000, 0x00401040, 0x80400040,
|
477 |
-
0x80001000, 0x00001040, 0x00400000, 0x80401000,
|
478 |
-
0x00000040, 0x00400000, 0x00001000, 0x00401040
|
479 |
-
);
|
480 |
-
|
481 |
-
/**
|
482 |
-
* Pre-permuted S-box5
|
483 |
-
*
|
484 |
-
* @var array
|
485 |
-
* @access private
|
486 |
-
*/
|
487 |
-
var $sbox5 = array(
|
488 |
-
0x00000080, 0x01040080, 0x01040000, 0x21000080,
|
489 |
-
0x00040000, 0x00000080, 0x20000000, 0x01040000,
|
490 |
-
0x20040080, 0x00040000, 0x01000080, 0x20040080,
|
491 |
-
0x21000080, 0x21040000, 0x00040080, 0x20000000,
|
492 |
-
0x01000000, 0x20040000, 0x20040000, 0x00000000,
|
493 |
-
0x20000080, 0x21040080, 0x21040080, 0x01000080,
|
494 |
-
0x21040000, 0x20000080, 0x00000000, 0x21000000,
|
495 |
-
0x01040080, 0x01000000, 0x21000000, 0x00040080,
|
496 |
-
0x00040000, 0x21000080, 0x00000080, 0x01000000,
|
497 |
-
0x20000000, 0x01040000, 0x21000080, 0x20040080,
|
498 |
-
0x01000080, 0x20000000, 0x21040000, 0x01040080,
|
499 |
-
0x20040080, 0x00000080, 0x01000000, 0x21040000,
|
500 |
-
0x21040080, 0x00040080, 0x21000000, 0x21040080,
|
501 |
-
0x01040000, 0x00000000, 0x20040000, 0x21000000,
|
502 |
-
0x00040080, 0x01000080, 0x20000080, 0x00040000,
|
503 |
-
0x00000000, 0x20040000, 0x01040080, 0x20000080
|
504 |
-
);
|
505 |
-
|
506 |
-
/**
|
507 |
-
* Pre-permuted S-box6
|
508 |
-
*
|
509 |
-
* @var array
|
510 |
-
* @access private
|
511 |
-
*/
|
512 |
-
var $sbox6 = array(
|
513 |
-
0x10000008, 0x10200000, 0x00002000, 0x10202008,
|
514 |
-
0x10200000, 0x00000008, 0x10202008, 0x00200000,
|
515 |
-
0x10002000, 0x00202008, 0x00200000, 0x10000008,
|
516 |
-
0x00200008, 0x10002000, 0x10000000, 0x00002008,
|
517 |
-
0x00000000, 0x00200008, 0x10002008, 0x00002000,
|
518 |
-
0x00202000, 0x10002008, 0x00000008, 0x10200008,
|
519 |
-
0x10200008, 0x00000000, 0x00202008, 0x10202000,
|
520 |
-
0x00002008, 0x00202000, 0x10202000, 0x10000000,
|
521 |
-
0x10002000, 0x00000008, 0x10200008, 0x00202000,
|
522 |
-
0x10202008, 0x00200000, 0x00002008, 0x10000008,
|
523 |
-
0x00200000, 0x10002000, 0x10000000, 0x00002008,
|
524 |
-
0x10000008, 0x10202008, 0x00202000, 0x10200000,
|
525 |
-
0x00202008, 0x10202000, 0x00000000, 0x10200008,
|
526 |
-
0x00000008, 0x00002000, 0x10200000, 0x00202008,
|
527 |
-
0x00002000, 0x00200008, 0x10002008, 0x00000000,
|
528 |
-
0x10202000, 0x10000000, 0x00200008, 0x10002008
|
529 |
-
);
|
530 |
-
|
531 |
-
/**
|
532 |
-
* Pre-permuted S-box7
|
533 |
-
*
|
534 |
-
* @var array
|
535 |
-
* @access private
|
536 |
-
*/
|
537 |
-
var $sbox7 = array(
|
538 |
-
0x00100000, 0x02100001, 0x02000401, 0x00000000,
|
539 |
-
0x00000400, 0x02000401, 0x00100401, 0x02100400,
|
540 |
-
0x02100401, 0x00100000, 0x00000000, 0x02000001,
|
541 |
-
0x00000001, 0x02000000, 0x02100001, 0x00000401,
|
542 |
-
0x02000400, 0x00100401, 0x00100001, 0x02000400,
|
543 |
-
0x02000001, 0x02100000, 0x02100400, 0x00100001,
|
544 |
-
0x02100000, 0x00000400, 0x00000401, 0x02100401,
|
545 |
-
0x00100400, 0x00000001, 0x02000000, 0x00100400,
|
546 |
-
0x02000000, 0x00100400, 0x00100000, 0x02000401,
|
547 |
-
0x02000401, 0x02100001, 0x02100001, 0x00000001,
|
548 |
-
0x00100001, 0x02000000, 0x02000400, 0x00100000,
|
549 |
-
0x02100400, 0x00000401, 0x00100401, 0x02100400,
|
550 |
-
0x00000401, 0x02000001, 0x02100401, 0x02100000,
|
551 |
-
0x00100400, 0x00000000, 0x00000001, 0x02100401,
|
552 |
-
0x00000000, 0x00100401, 0x02100000, 0x00000400,
|
553 |
-
0x02000001, 0x02000400, 0x00000400, 0x00100001
|
554 |
-
);
|
555 |
-
|
556 |
-
/**
|
557 |
-
* Pre-permuted S-box8
|
558 |
-
*
|
559 |
-
* @var array
|
560 |
-
* @access private
|
561 |
-
*/
|
562 |
-
var $sbox8 = array(
|
563 |
-
0x08000820, 0x00000800, 0x00020000, 0x08020820,
|
564 |
-
0x08000000, 0x08000820, 0x00000020, 0x08000000,
|
565 |
-
0x00020020, 0x08020000, 0x08020820, 0x00020800,
|
566 |
-
0x08020800, 0x00020820, 0x00000800, 0x00000020,
|
567 |
-
0x08020000, 0x08000020, 0x08000800, 0x00000820,
|
568 |
-
0x00020800, 0x00020020, 0x08020020, 0x08020800,
|
569 |
-
0x00000820, 0x00000000, 0x00000000, 0x08020020,
|
570 |
-
0x08000020, 0x08000800, 0x00020820, 0x00020000,
|
571 |
-
0x00020820, 0x00020000, 0x08020800, 0x00000800,
|
572 |
-
0x00000020, 0x08020020, 0x00000800, 0x00020820,
|
573 |
-
0x08000800, 0x00000020, 0x08000020, 0x08020000,
|
574 |
-
0x08020020, 0x08000000, 0x00020000, 0x08000820,
|
575 |
-
0x00000000, 0x08020820, 0x00020020, 0x08000020,
|
576 |
-
0x08020000, 0x08000800, 0x08000820, 0x00000000,
|
577 |
-
0x08020820, 0x00020800, 0x00020800, 0x00000820,
|
578 |
-
0x00000820, 0x00020020, 0x08000000, 0x08020800
|
579 |
-
);
|
580 |
-
|
581 |
-
/**
|
582 |
-
* Test for engine validity
|
583 |
-
*
|
584 |
-
* This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
|
585 |
-
*
|
586 |
-
* @see \phpseclib\Crypt\Base::isValidEngine()
|
587 |
-
* @param int $engine
|
588 |
-
* @access public
|
589 |
-
* @return bool
|
590 |
-
*/
|
591 |
-
function isValidEngine($engine)
|
592 |
-
{
|
593 |
-
if ($this->key_length_max == 8) {
|
594 |
-
if ($engine == self::ENGINE_OPENSSL) {
|
595 |
-
$this->cipher_name_openssl_ecb = 'des-ecb';
|
596 |
-
$this->cipher_name_openssl = 'des-' . $this->_openssl_translate_mode();
|
597 |
-
}
|
598 |
-
}
|
599 |
-
|
600 |
-
return parent::isValidEngine($engine);
|
601 |
-
}
|
602 |
-
|
603 |
-
/**
|
604 |
-
* Sets the key.
|
605 |
-
*
|
606 |
-
* Keys can be of any length. DES, itself, uses 64-bit keys (eg. strlen($key) == 8), however, we
|
607 |
-
* only use the first eight, if $key has more then eight characters in it, and pad $key with the
|
608 |
-
* null byte if it is less then eight characters long.
|
609 |
-
*
|
610 |
-
* DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
|
611 |
-
*
|
612 |
-
* If the key is not explicitly set, it'll be assumed to be all zero's.
|
613 |
-
*
|
614 |
-
* @see \phpseclib\Crypt\Base::setKey()
|
615 |
-
* @access public
|
616 |
-
* @param string $key
|
617 |
-
*/
|
618 |
-
function setKey($key)
|
619 |
-
{
|
620 |
-
// We check/cut here only up to max length of the key.
|
621 |
-
// Key padding to the proper length will be done in _setupKey()
|
622 |
-
if (strlen($key) > $this->key_length_max) {
|
623 |
-
$key = substr($key, 0, $this->key_length_max);
|
624 |
-
}
|
625 |
-
|
626 |
-
// Sets the key
|
627 |
-
parent::setKey($key);
|
628 |
-
}
|
629 |
-
|
630 |
-
/**
|
631 |
-
* Encrypts a block
|
632 |
-
*
|
633 |
-
* @see \phpseclib\Crypt\Base::_encryptBlock()
|
634 |
-
* @see \phpseclib\Crypt\Base::encrypt()
|
635 |
-
* @see self::encrypt()
|
636 |
-
* @access private
|
637 |
-
* @param string $in
|
638 |
-
* @return string
|
639 |
-
*/
|
640 |
-
function _encryptBlock($in)
|
641 |
-
{
|
642 |
-
return $this->_processBlock($in, self::ENCRYPT);
|
643 |
-
}
|
644 |
-
|
645 |
-
/**
|
646 |
-
* Decrypts a block
|
647 |
-
*
|
648 |
-
* @see \phpseclib\Crypt\Base::_decryptBlock()
|
649 |
-
* @see \phpseclib\Crypt\Base::decrypt()
|
650 |
-
* @see self::decrypt()
|
651 |
-
* @access private
|
652 |
-
* @param string $in
|
653 |
-
* @return string
|
654 |
-
*/
|
655 |
-
function _decryptBlock($in)
|
656 |
-
{
|
657 |
-
return $this->_processBlock($in, self::DECRYPT);
|
658 |
-
}
|
659 |
-
|
660 |
-
/**
|
661 |
-
* Encrypts or decrypts a 64-bit block
|
662 |
-
*
|
663 |
-
* $mode should be either self::ENCRYPT or self::DECRYPT. See
|
664 |
-
* {@link http://en.wikipedia.org/wiki/Image:Feistel.png Feistel.png} to get a general
|
665 |
-
* idea of what this function does.
|
666 |
-
*
|
667 |
-
* @see self::_encryptBlock()
|
668 |
-
* @see self::_decryptBlock()
|
669 |
-
* @access private
|
670 |
-
* @param string $block
|
671 |
-
* @param int $mode
|
672 |
-
* @return string
|
673 |
-
*/
|
674 |
-
function _processBlock($block, $mode)
|
675 |
-
{
|
676 |
-
static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip;
|
677 |
-
if (!$sbox1) {
|
678 |
-
$sbox1 = array_map("intval", $this->sbox1);
|
679 |
-
$sbox2 = array_map("intval", $this->sbox2);
|
680 |
-
$sbox3 = array_map("intval", $this->sbox3);
|
681 |
-
$sbox4 = array_map("intval", $this->sbox4);
|
682 |
-
$sbox5 = array_map("intval", $this->sbox5);
|
683 |
-
$sbox6 = array_map("intval", $this->sbox6);
|
684 |
-
$sbox7 = array_map("intval", $this->sbox7);
|
685 |
-
$sbox8 = array_map("intval", $this->sbox8);
|
686 |
-
/* Merge $shuffle with $[inv]ipmap */
|
687 |
-
for ($i = 0; $i < 256; ++$i) {
|
688 |
-
$shuffleip[] = $this->shuffle[$this->ipmap[$i]];
|
689 |
-
$shuffleinvip[] = $this->shuffle[$this->invipmap[$i]];
|
690 |
-
}
|
691 |
-
}
|
692 |
-
|
693 |
-
$keys = $this->keys[$mode];
|
694 |
-
$ki = -1;
|
695 |
-
|
696 |
-
// Do the initial IP permutation.
|
697 |
-
$t = unpack('Nl/Nr', $block);
|
698 |
-
list($l, $r) = array($t['l'], $t['r']);
|
699 |
-
$block = ($shuffleip[ $r & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") |
|
700 |
-
($shuffleip[($r >> 8) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") |
|
701 |
-
($shuffleip[($r >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") |
|
702 |
-
($shuffleip[($r >> 24) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") |
|
703 |
-
($shuffleip[ $l & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") |
|
704 |
-
($shuffleip[($l >> 8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") |
|
705 |
-
($shuffleip[($l >> 16) & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") |
|
706 |
-
($shuffleip[($l >> 24) & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01");
|
707 |
-
|
708 |
-
// Extract L0 and R0.
|
709 |
-
$t = unpack('Nl/Nr', $block);
|
710 |
-
list($l, $r) = array($t['l'], $t['r']);
|
711 |
-
|
712 |
-
for ($des_round = 0; $des_round < $this->des_rounds; ++$des_round) {
|
713 |
-
// Perform the 16 steps.
|
714 |
-
for ($i = 0; $i < 16; $i++) {
|
715 |
-
// start of "the Feistel (F) function" - see the following URL:
|
716 |
-
// http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png
|
717 |
-
// Merge key schedule.
|
718 |
-
$b1 = (($r >> 3) & 0x1FFFFFFF) ^ ($r << 29) ^ $keys[++$ki];
|
719 |
-
$b2 = (($r >> 31) & 0x00000001) ^ ($r << 1) ^ $keys[++$ki];
|
720 |
-
|
721 |
-
// S-box indexing.
|
722 |
-
$t = $sbox1[($b1 >> 24) & 0x3F] ^ $sbox2[($b2 >> 24) & 0x3F] ^
|
723 |
-
$sbox3[($b1 >> 16) & 0x3F] ^ $sbox4[($b2 >> 16) & 0x3F] ^
|
724 |
-
$sbox5[($b1 >> 8) & 0x3F] ^ $sbox6[($b2 >> 8) & 0x3F] ^
|
725 |
-
$sbox7[ $b1 & 0x3F] ^ $sbox8[ $b2 & 0x3F] ^ $l;
|
726 |
-
// end of "the Feistel (F) function"
|
727 |
-
|
728 |
-
$l = $r;
|
729 |
-
$r = $t;
|
730 |
-
}
|
731 |
-
|
732 |
-
// Last step should not permute L & R.
|
733 |
-
$t = $l;
|
734 |
-
$l = $r;
|
735 |
-
$r = $t;
|
736 |
-
}
|
737 |
-
|
738 |
-
// Perform the inverse IP permutation.
|
739 |
-
return ($shuffleinvip[($r >> 24) & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") |
|
740 |
-
($shuffleinvip[($l >> 24) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") |
|
741 |
-
($shuffleinvip[($r >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") |
|
742 |
-
($shuffleinvip[($l >> 16) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") |
|
743 |
-
($shuffleinvip[($r >> 8) & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") |
|
744 |
-
($shuffleinvip[($l >> 8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") |
|
745 |
-
($shuffleinvip[ $r & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") |
|
746 |
-
($shuffleinvip[ $l & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01");
|
747 |
-
}
|
748 |
-
|
749 |
-
/**
|
750 |
-
* Creates the key schedule
|
751 |
-
*
|
752 |
-
* @see \phpseclib\Crypt\Base::_setupKey()
|
753 |
-
* @access private
|
754 |
-
*/
|
755 |
-
function _setupKey()
|
756 |
-
{
|
757 |
-
if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->des_rounds === $this->kl['des_rounds']) {
|
758 |
-
// already expanded
|
759 |
-
return;
|
760 |
-
}
|
761 |
-
$this->kl = array('key' => $this->key, 'des_rounds' => $this->des_rounds);
|
762 |
-
|
763 |
-
static $shifts = array( // number of key bits shifted per round
|
764 |
-
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
|
765 |
-
);
|
766 |
-
|
767 |
-
static $pc1map = array(
|
768 |
-
0x00, 0x00, 0x08, 0x08, 0x04, 0x04, 0x0C, 0x0C,
|
769 |
-
0x02, 0x02, 0x0A, 0x0A, 0x06, 0x06, 0x0E, 0x0E,
|
770 |
-
0x10, 0x10, 0x18, 0x18, 0x14, 0x14, 0x1C, 0x1C,
|
771 |
-
0x12, 0x12, 0x1A, 0x1A, 0x16, 0x16, 0x1E, 0x1E,
|
772 |
-
0x20, 0x20, 0x28, 0x28, 0x24, 0x24, 0x2C, 0x2C,
|
773 |
-
0x22, 0x22, 0x2A, 0x2A, 0x26, 0x26, 0x2E, 0x2E,
|
774 |
-
0x30, 0x30, 0x38, 0x38, 0x34, 0x34, 0x3C, 0x3C,
|
775 |
-
0x32, 0x32, 0x3A, 0x3A, 0x36, 0x36, 0x3E, 0x3E,
|
776 |
-
0x40, 0x40, 0x48, 0x48, 0x44, 0x44, 0x4C, 0x4C,
|
777 |
-
0x42, 0x42, 0x4A, 0x4A, 0x46, 0x46, 0x4E, 0x4E,
|
778 |
-
0x50, 0x50, 0x58, 0x58, 0x54, 0x54, 0x5C, 0x5C,
|
779 |
-
0x52, 0x52, 0x5A, 0x5A, 0x56, 0x56, 0x5E, 0x5E,
|
780 |
-
0x60, 0x60, 0x68, 0x68, 0x64, 0x64, 0x6C, 0x6C,
|
781 |
-
0x62, 0x62, 0x6A, 0x6A, 0x66, 0x66, 0x6E, 0x6E,
|
782 |
-
0x70, 0x70, 0x78, 0x78, 0x74, 0x74, 0x7C, 0x7C,
|
783 |
-
0x72, 0x72, 0x7A, 0x7A, 0x76, 0x76, 0x7E, 0x7E,
|
784 |
-
0x80, 0x80, 0x88, 0x88, 0x84, 0x84, 0x8C, 0x8C,
|
785 |
-
0x82, 0x82, 0x8A, 0x8A, 0x86, 0x86, 0x8E, 0x8E,
|
786 |
-
0x90, 0x90, 0x98, 0x98, 0x94, 0x94, 0x9C, 0x9C,
|
787 |
-
0x92, 0x92, 0x9A, 0x9A, 0x96, 0x96, 0x9E, 0x9E,
|
788 |
-
0xA0, 0xA0, 0xA8, 0xA8, 0xA4, 0xA4, 0xAC, 0xAC,
|
789 |
-
0xA2, 0xA2, 0xAA, 0xAA, 0xA6, 0xA6, 0xAE, 0xAE,
|
790 |
-
0xB0, 0xB0, 0xB8, 0xB8, 0xB4, 0xB4, 0xBC, 0xBC,
|
791 |
-
0xB2, 0xB2, 0xBA, 0xBA, 0xB6, 0xB6, 0xBE, 0xBE,
|
792 |
-
0xC0, 0xC0, 0xC8, 0xC8, 0xC4, 0xC4, 0xCC, 0xCC,
|
793 |
-
0xC2, 0xC2, 0xCA, 0xCA, 0xC6, 0xC6, 0xCE, 0xCE,
|
794 |
-
0xD0, 0xD0, 0xD8, 0xD8, 0xD4, 0xD4, 0xDC, 0xDC,
|
795 |
-
0xD2, 0xD2, 0xDA, 0xDA, 0xD6, 0xD6, 0xDE, 0xDE,
|
796 |
-
0xE0, 0xE0, 0xE8, 0xE8, 0xE4, 0xE4, 0xEC, 0xEC,
|
797 |
-
0xE2, 0xE2, 0xEA, 0xEA, 0xE6, 0xE6, 0xEE, 0xEE,
|
798 |
-
0xF0, 0xF0, 0xF8, 0xF8, 0xF4, 0xF4, 0xFC, 0xFC,
|
799 |
-
0xF2, 0xF2, 0xFA, 0xFA, 0xF6, 0xF6, 0xFE, 0xFE
|
800 |
-
);
|
801 |
-
|
802 |
-
// Mapping tables for the PC-2 transformation.
|
803 |
-
static $pc2mapc1 = array(
|
804 |
-
0x00000000, 0x00000400, 0x00200000, 0x00200400,
|
805 |
-
0x00000001, 0x00000401, 0x00200001, 0x00200401,
|
806 |
-
0x02000000, 0x02000400, 0x02200000, 0x02200400,
|
807 |
-
0x02000001, 0x02000401, 0x02200001, 0x02200401
|
808 |
-
);
|
809 |
-
static $pc2mapc2 = array(
|
810 |
-
0x00000000, 0x00000800, 0x08000000, 0x08000800,
|
811 |
-
0x00010000, 0x00010800, 0x08010000, 0x08010800,
|
812 |
-
0x00000000, 0x00000800, 0x08000000, 0x08000800,
|
813 |
-
0x00010000, 0x00010800, 0x08010000, 0x08010800,
|
814 |
-
0x00000100, 0x00000900, 0x08000100, 0x08000900,
|
815 |
-
0x00010100, 0x00010900, 0x08010100, 0x08010900,
|
816 |
-
0x00000100, 0x00000900, 0x08000100, 0x08000900,
|
817 |
-
0x00010100, 0x00010900, 0x08010100, 0x08010900,
|
818 |
-
0x00000010, 0x00000810, 0x08000010, 0x08000810,
|
819 |
-
0x00010010, 0x00010810, 0x08010010, 0x08010810,
|
820 |
-
0x00000010, 0x00000810, 0x08000010, 0x08000810,
|
821 |
-
0x00010010, 0x00010810, 0x08010010, 0x08010810,
|
822 |
-
0x00000110, 0x00000910, 0x08000110, 0x08000910,
|
823 |
-
0x00010110, 0x00010910, 0x08010110, 0x08010910,
|
824 |
-
0x00000110, 0x00000910, 0x08000110, 0x08000910,
|
825 |
-
0x00010110, 0x00010910, 0x08010110, 0x08010910,
|
826 |
-
0x00040000, 0x00040800, 0x08040000, 0x08040800,
|
827 |
-
0x00050000, 0x00050800, 0x08050000, 0x08050800,
|
828 |
-
0x00040000, 0x00040800, 0x08040000, 0x08040800,
|
829 |
-
0x00050000, 0x00050800, 0x08050000, 0x08050800,
|
830 |
-
0x00040100, 0x00040900, 0x08040100, 0x08040900,
|
831 |
-
0x00050100, 0x00050900, 0x08050100, 0x08050900,
|
832 |
-
0x00040100, 0x00040900, 0x08040100, 0x08040900,
|
833 |
-
0x00050100, 0x00050900, 0x08050100, 0x08050900,
|
834 |
-
0x00040010, 0x00040810, 0x08040010, 0x08040810,
|
835 |
-
0x00050010, 0x00050810, 0x08050010, 0x08050810,
|
836 |
-
0x00040010, 0x00040810, 0x08040010, 0x08040810,
|
837 |
-
0x00050010, 0x00050810, 0x08050010, 0x08050810,
|
838 |
-
0x00040110, 0x00040910, 0x08040110, 0x08040910,
|
839 |
-
0x00050110, 0x00050910, 0x08050110, 0x08050910,
|
840 |
-
0x00040110, 0x00040910, 0x08040110, 0x08040910,
|
841 |
-
0x00050110, 0x00050910, 0x08050110, 0x08050910,
|
842 |
-
0x01000000, 0x01000800, 0x09000000, 0x09000800,
|
843 |
-
0x01010000, 0x01010800, 0x09010000, 0x09010800,
|
844 |
-
0x01000000, 0x01000800, 0x09000000, 0x09000800,
|
845 |
-
0x01010000, 0x01010800, 0x09010000, 0x09010800,
|
846 |
-
0x01000100, 0x01000900, 0x09000100, 0x09000900,
|
847 |
-
0x01010100, 0x01010900, 0x09010100, 0x09010900,
|
848 |
-
0x01000100, 0x01000900, 0x09000100, 0x09000900,
|
849 |
-
0x01010100, 0x01010900, 0x09010100, 0x09010900,
|
850 |
-
0x01000010, 0x01000810, 0x09000010, 0x09000810,
|
851 |
-
0x01010010, 0x01010810, 0x09010010, 0x09010810,
|
852 |
-
0x01000010, 0x01000810, 0x09000010, 0x09000810,
|
853 |
-
0x01010010, 0x01010810, 0x09010010, 0x09010810,
|
854 |
-
0x01000110, 0x01000910, 0x09000110, 0x09000910,
|
855 |
-
0x01010110, 0x01010910, 0x09010110, 0x09010910,
|
856 |
-
0x01000110, 0x01000910, 0x09000110, 0x09000910,
|
857 |
-
0x01010110, 0x01010910, 0x09010110, 0x09010910,
|
858 |
-
0x01040000, 0x01040800, 0x09040000, 0x09040800,
|
859 |
-
0x01050000, 0x01050800, 0x09050000, 0x09050800,
|
860 |
-
0x01040000, 0x01040800, 0x09040000, 0x09040800,
|
861 |
-
0x01050000, 0x01050800, 0x09050000, 0x09050800,
|
862 |
-
0x01040100, 0x01040900, 0x09040100, 0x09040900,
|
863 |
-
0x01050100, 0x01050900, 0x09050100, 0x09050900,
|
864 |
-
0x01040100, 0x01040900, 0x09040100, 0x09040900,
|
865 |
-
0x01050100, 0x01050900, 0x09050100, 0x09050900,
|
866 |
-
0x01040010, 0x01040810, 0x09040010, 0x09040810,
|
867 |
-
0x01050010, 0x01050810, 0x09050010, 0x09050810,
|
868 |
-
0x01040010, 0x01040810, 0x09040010, 0x09040810,
|
869 |
-
0x01050010, 0x01050810, 0x09050010, 0x09050810,
|
870 |
-
0x01040110, 0x01040910, 0x09040110, 0x09040910,
|
871 |
-
0x01050110, 0x01050910, 0x09050110, 0x09050910,
|
872 |
-
0x01040110, 0x01040910, 0x09040110, 0x09040910,
|
873 |
-
0x01050110, 0x01050910, 0x09050110, 0x09050910
|
874 |
-
);
|
875 |
-
static $pc2mapc3 = array(
|
876 |
-
0x00000000, 0x00000004, 0x00001000, 0x00001004,
|
877 |
-
0x00000000, 0x00000004, 0x00001000, 0x00001004,
|
878 |
-
0x10000000, 0x10000004, 0x10001000, 0x10001004,
|
879 |
-
0x10000000, 0x10000004, 0x10001000, 0x10001004,
|
880 |
-
0x00000020, 0x00000024, 0x00001020, 0x00001024,
|
881 |
-
0x00000020, 0x00000024, 0x00001020, 0x00001024,
|
882 |
-
0x10000020, 0x10000024, 0x10001020, 0x10001024,
|
883 |
-
0x10000020, 0x10000024, 0x10001020, 0x10001024,
|
884 |
-
0x00080000, 0x00080004, 0x00081000, 0x00081004,
|
885 |
-
0x00080000, 0x00080004, 0x00081000, 0x00081004,
|
886 |
-
0x10080000, 0x10080004, 0x10081000, 0x10081004,
|
887 |
-
0x10080000, 0x10080004, 0x10081000, 0x10081004,
|
888 |
-
0x00080020, 0x00080024, 0x00081020, 0x00081024,
|
889 |
-
0x00080020, 0x00080024, 0x00081020, 0x00081024,
|
890 |
-
0x10080020, 0x10080024, 0x10081020, 0x10081024,
|
891 |
-
0x10080020, 0x10080024, 0x10081020, 0x10081024,
|
892 |
-
0x20000000, 0x20000004, 0x20001000, 0x20001004,
|
893 |
-
0x20000000, 0x20000004, 0x20001000, 0x20001004,
|
894 |
-
0x30000000, 0x30000004, 0x30001000, 0x30001004,
|
895 |
-
0x30000000, 0x30000004, 0x30001000, 0x30001004,
|
896 |
-
0x20000020, 0x20000024, 0x20001020, 0x20001024,
|
897 |
-
0x20000020, 0x20000024, 0x20001020, 0x20001024,
|
898 |
-
0x30000020, 0x30000024, 0x30001020, 0x30001024,
|
899 |
-
0x30000020, 0x30000024, 0x30001020, 0x30001024,
|
900 |
-
0x20080000, 0x20080004, 0x20081000, 0x20081004,
|
901 |
-
0x20080000, 0x20080004, 0x20081000, 0x20081004,
|
902 |
-
0x30080000, 0x30080004, 0x30081000, 0x30081004,
|
903 |
-
0x30080000, 0x30080004, 0x30081000, 0x30081004,
|
904 |
-
0x20080020, 0x20080024, 0x20081020, 0x20081024,
|
905 |
-
0x20080020, 0x20080024, 0x20081020, 0x20081024,
|
906 |
-
0x30080020, 0x30080024, 0x30081020, 0x30081024,
|
907 |
-
0x30080020, 0x30080024, 0x30081020, 0x30081024,
|
908 |
-
0x00000002, 0x00000006, 0x00001002, 0x00001006,
|
909 |
-
0x00000002, 0x00000006, 0x00001002, 0x00001006,
|
910 |
-
0x10000002, 0x10000006, 0x10001002, 0x10001006,
|
911 |
-
0x10000002, 0x10000006, 0x10001002, 0x10001006,
|
912 |
-
0x00000022, 0x00000026, 0x00001022, 0x00001026,
|
913 |
-
0x00000022, 0x00000026, 0x00001022, 0x00001026,
|
914 |
-
0x10000022, 0x10000026, 0x10001022, 0x10001026,
|
915 |
-
0x10000022, 0x10000026, 0x10001022, 0x10001026,
|
916 |
-
0x00080002, 0x00080006, 0x00081002, 0x00081006,
|
917 |
-
0x00080002, 0x00080006, 0x00081002, 0x00081006,
|
918 |
-
0x10080002, 0x10080006, 0x10081002, 0x10081006,
|
919 |
-
0x10080002, 0x10080006, 0x10081002, 0x10081006,
|
920 |
-
0x00080022, 0x00080026, 0x00081022, 0x00081026,
|
921 |
-
0x00080022, 0x00080026, 0x00081022, 0x00081026,
|
922 |
-
0x10080022, 0x10080026, 0x10081022, 0x10081026,
|
923 |
-
0x10080022, 0x10080026, 0x10081022, 0x10081026,
|
924 |
-
0x20000002, 0x20000006, 0x20001002, 0x20001006,
|
925 |
-
0x20000002, 0x20000006, 0x20001002, 0x20001006,
|
926 |
-
0x30000002, 0x30000006, 0x30001002, 0x30001006,
|
927 |
-
0x30000002, 0x30000006, 0x30001002, 0x30001006,
|
928 |
-
0x20000022, 0x20000026, 0x20001022, 0x20001026,
|
929 |
-
0x20000022, 0x20000026, 0x20001022, 0x20001026,
|
930 |
-
0x30000022, 0x30000026, 0x30001022, 0x30001026,
|
931 |
-
0x30000022, 0x30000026, 0x30001022, 0x30001026,
|
932 |
-
0x20080002, 0x20080006, 0x20081002, 0x20081006,
|
933 |
-
0x20080002, 0x20080006, 0x20081002, 0x20081006,
|
934 |
-
0x30080002, 0x30080006, 0x30081002, 0x30081006,
|
935 |
-
0x30080002, 0x30080006, 0x30081002, 0x30081006,
|
936 |
-
0x20080022, 0x20080026, 0x20081022, 0x20081026,
|
937 |
-
0x20080022, 0x20080026, 0x20081022, 0x20081026,
|
938 |
-
0x30080022, 0x30080026, 0x30081022, 0x30081026,
|
939 |
-
0x30080022, 0x30080026, 0x30081022, 0x30081026
|
940 |
-
);
|
941 |
-
static $pc2mapc4 = array(
|
942 |
-
0x00000000, 0x00100000, 0x00000008, 0x00100008,
|
943 |
-
0x00000200, 0x00100200, 0x00000208, 0x00100208,
|
944 |
-
0x00000000, 0x00100000, 0x00000008, 0x00100008,
|
945 |
-
0x00000200, 0x00100200, 0x00000208, 0x00100208,
|
946 |
-
0x04000000, 0x04100000, 0x04000008, 0x04100008,
|
947 |
-
0x04000200, 0x04100200, 0x04000208, 0x04100208,
|
948 |
-
0x04000000, 0x04100000, 0x04000008, 0x04100008,
|
949 |
-
0x04000200, 0x04100200, 0x04000208, 0x04100208,
|
950 |
-
0x00002000, 0x00102000, 0x00002008, 0x00102008,
|
951 |
-
0x00002200, 0x00102200, 0x00002208, 0x00102208,
|
952 |
-
0x00002000, 0x00102000, 0x00002008, 0x00102008,
|
953 |
-
0x00002200, 0x00102200, 0x00002208, 0x00102208,
|
954 |
-
0x04002000, 0x04102000, 0x04002008, 0x04102008,
|
955 |
-
0x04002200, 0x04102200, 0x04002208, 0x04102208,
|
956 |
-
0x04002000, 0x04102000, 0x04002008, 0x04102008,
|
957 |
-
0x04002200, 0x04102200, 0x04002208, 0x04102208,
|
958 |
-
0x00000000, 0x00100000, 0x00000008, 0x00100008,
|
959 |
-
0x00000200, 0x00100200, 0x00000208, 0x00100208,
|
960 |
-
0x00000000, 0x00100000, 0x00000008, 0x00100008,
|
961 |
-
0x00000200, 0x00100200, 0x00000208, 0x00100208,
|
962 |
-
0x04000000, 0x04100000, 0x04000008, 0x04100008,
|
963 |
-
0x04000200, 0x04100200, 0x04000208, 0x04100208,
|
964 |
-
0x04000000, 0x04100000, 0x04000008, 0x04100008,
|
965 |
-
0x04000200, 0x04100200, 0x04000208, 0x04100208,
|
966 |
-
0x00002000, 0x00102000, 0x00002008, 0x00102008,
|
967 |
-
0x00002200, 0x00102200, 0x00002208, 0x00102208,
|
968 |
-
0x00002000, 0x00102000, 0x00002008, 0x00102008,
|
969 |
-
0x00002200, 0x00102200, 0x00002208, 0x00102208,
|
970 |
-
0x04002000, 0x04102000, 0x04002008, 0x04102008,
|
971 |
-
0x04002200, 0x04102200, 0x04002208, 0x04102208,
|
972 |
-
0x04002000, 0x04102000, 0x04002008, 0x04102008,
|
973 |
-
0x04002200, 0x04102200, 0x04002208, 0x04102208,
|
974 |
-
0x00020000, 0x00120000, 0x00020008, 0x00120008,
|
975 |
-
0x00020200, 0x00120200, 0x00020208, 0x00120208,
|
976 |
-
0x00020000, 0x00120000, 0x00020008, 0x00120008,
|
977 |
-
0x00020200, 0x00120200, 0x00020208, 0x00120208,
|
978 |
-
0x04020000, 0x04120000, 0x04020008, 0x04120008,
|
979 |
-
0x04020200, 0x04120200, 0x04020208, 0x04120208,
|
980 |
-
0x04020000, 0x04120000, 0x04020008, 0x04120008,
|
981 |
-
0x04020200, 0x04120200, 0x04020208, 0x04120208,
|
982 |
-
0x00022000, 0x00122000, 0x00022008, 0x00122008,
|
983 |
-
0x00022200, 0x00122200, 0x00022208, 0x00122208,
|
984 |
-
0x00022000, 0x00122000, 0x00022008, 0x00122008,
|
985 |
-
0x00022200, 0x00122200, 0x00022208, 0x00122208,
|
986 |
-
0x04022000, 0x04122000, 0x04022008, 0x04122008,
|
987 |
-
0x04022200, 0x04122200, 0x04022208, 0x04122208,
|
988 |
-
0x04022000, 0x04122000, 0x04022008, 0x04122008,
|
989 |
-
0x04022200, 0x04122200, 0x04022208, 0x04122208,
|
990 |
-
0x00020000, 0x00120000, 0x00020008, 0x00120008,
|
991 |
-
0x00020200, 0x00120200, 0x00020208, 0x00120208,
|
992 |
-
0x00020000, 0x00120000, 0x00020008, 0x00120008,
|
993 |
-
0x00020200, 0x00120200, 0x00020208, 0x00120208,
|
994 |
-
0x04020000, 0x04120000, 0x04020008, 0x04120008,
|
995 |
-
0x04020200, 0x04120200, 0x04020208, 0x04120208,
|
996 |
-
0x04020000, 0x04120000, 0x04020008, 0x04120008,
|
997 |
-
0x04020200, 0x04120200, 0x04020208, 0x04120208,
|
998 |
-
0x00022000, 0x00122000, 0x00022008, 0x00122008,
|
999 |
-
0x00022200, 0x00122200, 0x00022208, 0x00122208,
|
1000 |
-
0x00022000, 0x00122000, 0x00022008, 0x00122008,
|
1001 |
-
0x00022200, 0x00122200, 0x00022208, 0x00122208,
|
1002 |
-
0x04022000, 0x04122000, 0x04022008, 0x04122008,
|
1003 |
-
0x04022200, 0x04122200, 0x04022208, 0x04122208,
|
1004 |
-
0x04022000, 0x04122000, 0x04022008, 0x04122008,
|
1005 |
-
0x04022200, 0x04122200, 0x04022208, 0x04122208
|
1006 |
-
);
|
1007 |
-
static $pc2mapd1 = array(
|
1008 |
-
0x00000000, 0x00000001, 0x08000000, 0x08000001,
|
1009 |
-
0x00200000, 0x00200001, 0x08200000, 0x08200001,
|
1010 |
-
0x00000002, 0x00000003, 0x08000002, 0x08000003,
|
1011 |
-
0x00200002, 0x00200003, 0x08200002, 0x08200003
|
1012 |
-
);
|
1013 |
-
static $pc2mapd2 = array(
|
1014 |
-
0x00000000, 0x00100000, 0x00000800, 0x00100800,
|
1015 |
-
0x00000000, 0x00100000, 0x00000800, 0x00100800,
|
1016 |
-
0x04000000, 0x04100000, 0x04000800, 0x04100800,
|
1017 |
-
0x04000000, 0x04100000, 0x04000800, 0x04100800,
|
1018 |
-
0x00000004, 0x00100004, 0x00000804, 0x00100804,
|
1019 |
-
0x00000004, 0x00100004, 0x00000804, 0x00100804,
|
1020 |
-
0x04000004, 0x04100004, 0x04000804, 0x04100804,
|
1021 |
-
0x04000004, 0x04100004, 0x04000804, 0x04100804,
|
1022 |
-
0x00000000, 0x00100000, 0x00000800, 0x00100800,
|
1023 |
-
0x00000000, 0x00100000, 0x00000800, 0x00100800,
|
1024 |
-
0x04000000, 0x04100000, 0x04000800, 0x04100800,
|
1025 |
-
0x04000000, 0x04100000, 0x04000800, 0x04100800,
|
1026 |
-
0x00000004, 0x00100004, 0x00000804, 0x00100804,
|
1027 |
-
0x00000004, 0x00100004, 0x00000804, 0x00100804,
|
1028 |
-
0x04000004, 0x04100004, 0x04000804, 0x04100804,
|
1029 |
-
0x04000004, 0x04100004, 0x04000804, 0x04100804,
|
1030 |
-
0x00000200, 0x00100200, 0x00000A00, 0x00100A00,
|
1031 |
-
0x00000200, 0x00100200, 0x00000A00, 0x00100A00,
|
1032 |
-
0x04000200, 0x04100200, 0x04000A00, 0x04100A00,
|
1033 |
-
0x04000200, 0x04100200, 0x04000A00, 0x04100A00,
|
1034 |
-
0x00000204, 0x00100204, 0x00000A04, 0x00100A04,
|
1035 |
-
0x00000204, 0x00100204, 0x00000A04, 0x00100A04,
|
1036 |
-
0x04000204, 0x04100204, 0x04000A04, 0x04100A04,
|
1037 |
-
0x04000204, 0x04100204, 0x04000A04, 0x04100A04,
|
1038 |
-
0x00000200, 0x00100200, 0x00000A00, 0x00100A00,
|
1039 |
-
0x00000200, 0x00100200, 0x00000A00, 0x00100A00,
|
1040 |
-
0x04000200, 0x04100200, 0x04000A00, 0x04100A00,
|
1041 |
-
0x04000200, 0x04100200, 0x04000A00, 0x04100A00,
|
1042 |
-
0x00000204, 0x00100204, 0x00000A04, 0x00100A04,
|
1043 |
-
0x00000204, 0x00100204, 0x00000A04, 0x00100A04,
|
1044 |
-
0x04000204, 0x04100204, 0x04000A04, 0x04100A04,
|
1045 |
-
0x04000204, 0x04100204, 0x04000A04, 0x04100A04,
|
1046 |
-
0x00020000, 0x00120000, 0x00020800, 0x00120800,
|
1047 |
-
0x00020000, 0x00120000, 0x00020800, 0x00120800,
|
1048 |
-
0x04020000, 0x04120000, 0x04020800, 0x04120800,
|
1049 |
-
0x04020000, 0x04120000, 0x04020800, 0x04120800,
|
1050 |
-
0x00020004, 0x00120004, 0x00020804, 0x00120804,
|
1051 |
-
0x00020004, 0x00120004, 0x00020804, 0x00120804,
|
1052 |
-
0x04020004, 0x04120004, 0x04020804, 0x04120804,
|
1053 |
-
0x04020004, 0x04120004, 0x04020804, 0x04120804,
|
1054 |
-
0x00020000, 0x00120000, 0x00020800, 0x00120800,
|
1055 |
-
0x00020000, 0x00120000, 0x00020800, 0x00120800,
|
1056 |
-
0x04020000, 0x04120000, 0x04020800, 0x04120800,
|
1057 |
-
0x04020000, 0x04120000, 0x04020800, 0x04120800,
|
1058 |
-
0x00020004, 0x00120004, 0x00020804, 0x00120804,
|
1059 |
-
0x00020004, 0x00120004, 0x00020804, 0x00120804,
|
1060 |
-
0x04020004, 0x04120004, 0x04020804, 0x04120804,
|
1061 |
-
0x04020004, 0x04120004, 0x04020804, 0x04120804,
|
1062 |
-
0x00020200, 0x00120200, 0x00020A00, 0x00120A00,
|
1063 |
-
0x00020200, 0x00120200, 0x00020A00, 0x00120A00,
|
1064 |
-
0x04020200, 0x04120200, 0x04020A00, 0x04120A00,
|
1065 |
-
0x04020200, 0x04120200, 0x04020A00, 0x04120A00,
|
1066 |
-
0x00020204, 0x00120204, 0x00020A04, 0x00120A04,
|
1067 |
-
0x00020204, 0x00120204, 0x00020A04, 0x00120A04,
|
1068 |
-
0x04020204, 0x04120204, 0x04020A04, 0x04120A04,
|
1069 |
-
0x04020204, 0x04120204, 0x04020A04, 0x04120A04,
|
1070 |
-
0x00020200, 0x00120200, 0x00020A00, 0x00120A00,
|
1071 |
-
0x00020200, 0x00120200, 0x00020A00, 0x00120A00,
|
1072 |
-
0x04020200, 0x04120200, 0x04020A00, 0x04120A00,
|
1073 |
-
0x04020200, 0x04120200, 0x04020A00, 0x04120A00,
|
1074 |
-
0x00020204, 0x00120204, 0x00020A04, 0x00120A04,
|
1075 |
-
0x00020204, 0x00120204, 0x00020A04, 0x00120A04,
|
1076 |
-
0x04020204, 0x04120204, 0x04020A04, 0x04120A04,
|
1077 |
-
0x04020204, 0x04120204, 0x04020A04, 0x04120A04
|
1078 |
-
);
|
1079 |
-
static $pc2mapd3 = array(
|
1080 |
-
0x00000000, 0x00010000, 0x02000000, 0x02010000,
|
1081 |
-
0x00000020, 0x00010020, 0x02000020, 0x02010020,
|
1082 |
-
0x00040000, 0x00050000, 0x02040000, 0x02050000,
|
1083 |
-
0x00040020, 0x00050020, 0x02040020, 0x02050020,
|
1084 |
-
0x00002000, 0x00012000, 0x02002000, 0x02012000,
|
1085 |
-
0x00002020, 0x00012020, 0x02002020, 0x02012020,
|
1086 |
-
0x00042000, 0x00052000, 0x02042000, 0x02052000,
|
1087 |
-
0x00042020, 0x00052020, 0x02042020, 0x02052020,
|
1088 |
-
0x00000000, 0x00010000, 0x02000000, 0x02010000,
|
1089 |
-
0x00000020, 0x00010020, 0x02000020, 0x02010020,
|
1090 |
-
0x00040000, 0x00050000, 0x02040000, 0x02050000,
|
1091 |
-
0x00040020, 0x00050020, 0x02040020, 0x02050020,
|
1092 |
-
0x00002000, 0x00012000, 0x02002000, 0x02012000,
|
1093 |
-
0x00002020, 0x00012020, 0x02002020, 0x02012020,
|
1094 |
-
0x00042000, 0x00052000, 0x02042000, 0x02052000,
|
1095 |
-
0x00042020, 0x00052020, 0x02042020, 0x02052020,
|
1096 |
-
0x00000010, 0x00010010, 0x02000010, 0x02010010,
|
1097 |
-
0x00000030, 0x00010030, 0x02000030, 0x02010030,
|
1098 |
-
0x00040010, 0x00050010, 0x02040010, 0x02050010,
|
1099 |
-
0x00040030, 0x00050030, 0x02040030, 0x02050030,
|
1100 |
-
0x00002010, 0x00012010, 0x02002010, 0x02012010,
|
1101 |
-
0x00002030, 0x00012030, 0x02002030, 0x02012030,
|
1102 |
-
0x00042010, 0x00052010, 0x02042010, 0x02052010,
|
1103 |
-
0x00042030, 0x00052030, 0x02042030, 0x02052030,
|
1104 |
-
0x00000010, 0x00010010, 0x02000010, 0x02010010,
|
1105 |
-
0x00000030, 0x00010030, 0x02000030, 0x02010030,
|
1106 |
-
0x00040010, 0x00050010, 0x02040010, 0x02050010,
|
1107 |
-
0x00040030, 0x00050030, 0x02040030, 0x02050030,
|
1108 |
-
0x00002010, 0x00012010, 0x02002010, 0x02012010,
|
1109 |
-
0x00002030, 0x00012030, 0x02002030, 0x02012030,
|
1110 |
-
0x00042010, 0x00052010, 0x02042010, 0x02052010,
|
1111 |
-
0x00042030, 0x00052030, 0x02042030, 0x02052030,
|
1112 |
-
0x20000000, 0x20010000, 0x22000000, 0x22010000,
|
1113 |
-
0x20000020, 0x20010020, 0x22000020, 0x22010020,
|
1114 |
-
0x20040000, 0x20050000, 0x22040000, 0x22050000,
|
1115 |
-
0x20040020, 0x20050020, 0x22040020, 0x22050020,
|
1116 |
-
0x20002000, 0x20012000, 0x22002000, 0x22012000,
|
1117 |
-
0x20002020, 0x20012020, 0x22002020, 0x22012020,
|
1118 |
-
0x20042000, 0x20052000, 0x22042000, 0x22052000,
|
1119 |
-
0x20042020, 0x20052020, 0x22042020, 0x22052020,
|
1120 |
-
0x20000000, 0x20010000, 0x22000000, 0x22010000,
|
1121 |
-
0x20000020, 0x20010020, 0x22000020, 0x22010020,
|
1122 |
-
0x20040000, 0x20050000, 0x22040000, 0x22050000,
|
1123 |
-
0x20040020, 0x20050020, 0x22040020, 0x22050020,
|
1124 |
-
0x20002000, 0x20012000, 0x22002000, 0x22012000,
|
1125 |
-
0x20002020, 0x20012020, 0x22002020, 0x22012020,
|
1126 |
-
0x20042000, 0x20052000, 0x22042000, 0x22052000,
|
1127 |
-
0x20042020, 0x20052020, 0x22042020, 0x22052020,
|
1128 |
-
0x20000010, 0x20010010, 0x22000010, 0x22010010,
|
1129 |
-
0x20000030, 0x20010030, 0x22000030, 0x22010030,
|
1130 |
-
0x20040010, 0x20050010, 0x22040010, 0x22050010,
|
1131 |
-
0x20040030, 0x20050030, 0x22040030, 0x22050030,
|
1132 |
-
0x20002010, 0x20012010, 0x22002010, 0x22012010,
|
1133 |
-
0x20002030, 0x20012030, 0x22002030, 0x22012030,
|
1134 |
-
0x20042010, 0x20052010, 0x22042010, 0x22052010,
|
1135 |
-
0x20042030, 0x20052030, 0x22042030, 0x22052030,
|
1136 |
-
0x20000010, 0x20010010, 0x22000010, 0x22010010,
|
1137 |
-
0x20000030, 0x20010030, 0x22000030, 0x22010030,
|
1138 |
-
0x20040010, 0x20050010, 0x22040010, 0x22050010,
|
1139 |
-
0x20040030, 0x20050030, 0x22040030, 0x22050030,
|
1140 |
-
0x20002010, 0x20012010, 0x22002010, 0x22012010,
|
1141 |
-
0x20002030, 0x20012030, 0x22002030, 0x22012030,
|
1142 |
-
0x20042010, 0x20052010, 0x22042010, 0x22052010,
|
1143 |
-
0x20042030, 0x20052030, 0x22042030, 0x22052030
|
1144 |
-
);
|
1145 |
-
static $pc2mapd4 = array(
|
1146 |
-
0x00000000, 0x00000400, 0x01000000, 0x01000400,
|
1147 |
-
0x00000000, 0x00000400, 0x01000000, 0x01000400,
|
1148 |
-
0x00000100, 0x00000500, 0x01000100, 0x01000500,
|
1149 |
-
0x00000100, 0x00000500, 0x01000100, 0x01000500,
|
1150 |
-
0x10000000, 0x10000400, 0x11000000, 0x11000400,
|
1151 |
-
0x10000000, 0x10000400, 0x11000000, 0x11000400,
|
1152 |
-
0x10000100, 0x10000500, 0x11000100, 0x11000500,
|
1153 |
-
0x10000100, 0x10000500, 0x11000100, 0x11000500,
|
1154 |
-
0x00080000, 0x00080400, 0x01080000, 0x01080400,
|
1155 |
-
0x00080000, 0x00080400, 0x01080000, 0x01080400,
|
1156 |
-
0x00080100, 0x00080500, 0x01080100, 0x01080500,
|
1157 |
-
0x00080100, 0x00080500, 0x01080100, 0x01080500,
|
1158 |
-
0x10080000, 0x10080400, 0x11080000, 0x11080400,
|
1159 |
-
0x10080000, 0x10080400, 0x11080000, 0x11080400,
|
1160 |
-
0x10080100, 0x10080500, 0x11080100, 0x11080500,
|
1161 |
-
0x10080100, 0x10080500, 0x11080100, 0x11080500,
|
1162 |
-
0x00000008, 0x00000408, 0x01000008, 0x01000408,
|
1163 |
-
0x00000008, 0x00000408, 0x01000008, 0x01000408,
|
1164 |
-
0x00000108, 0x00000508, 0x01000108, 0x01000508,
|
1165 |
-
0x00000108, 0x00000508, 0x01000108, 0x01000508,
|
1166 |
-
0x10000008, 0x10000408, 0x11000008, 0x11000408,
|
1167 |
-
0x10000008, 0x10000408, 0x11000008, 0x11000408,
|
1168 |
-
0x10000108, 0x10000508, 0x11000108, 0x11000508,
|
1169 |
-
0x10000108, 0x10000508, 0x11000108, 0x11000508,
|
1170 |
-
0x00080008, 0x00080408, 0x01080008, 0x01080408,
|
1171 |
-
0x00080008, 0x00080408, 0x01080008, 0x01080408,
|
1172 |
-
0x00080108, 0x00080508, 0x01080108, 0x01080508,
|
1173 |
-
0x00080108, 0x00080508, 0x01080108, 0x01080508,
|
1174 |
-
0x10080008, 0x10080408, 0x11080008, 0x11080408,
|
1175 |
-
0x10080008, 0x10080408, 0x11080008, 0x11080408,
|
1176 |
-
0x10080108, 0x10080508, 0x11080108, 0x11080508,
|
1177 |
-
0x10080108, 0x10080508, 0x11080108, 0x11080508,
|
1178 |
-
0x00001000, 0x00001400, 0x01001000, 0x01001400,
|
1179 |
-
0x00001000, 0x00001400, 0x01001000, 0x01001400,
|
1180 |
-
0x00001100, 0x00001500, 0x01001100, 0x01001500,
|
1181 |
-
0x00001100, 0x00001500, 0x01001100, 0x01001500,
|
1182 |
-
0x10001000, 0x10001400, 0x11001000, 0x11001400,
|
1183 |
-
0x10001000, 0x10001400, 0x11001000, 0x11001400,
|
1184 |
-
0x10001100, 0x10001500, 0x11001100, 0x11001500,
|
1185 |
-
0x10001100, 0x10001500, 0x11001100, 0x11001500,
|
1186 |
-
0x00081000, 0x00081400, 0x01081000, 0x01081400,
|
1187 |
-
0x00081000, 0x00081400, 0x01081000, 0x01081400,
|
1188 |
-
0x00081100, 0x00081500, 0x01081100, 0x01081500,
|
1189 |
-
0x00081100, 0x00081500, 0x01081100, 0x01081500,
|
1190 |
-
0x10081000, 0x10081400, 0x11081000, 0x11081400,
|
1191 |
-
0x10081000, 0x10081400, 0x11081000, 0x11081400,
|
1192 |
-
0x10081100, 0x10081500, 0x11081100, 0x11081500,
|
1193 |
-
0x10081100, 0x10081500, 0x11081100, 0x11081500,
|
1194 |
-
0x00001008, 0x00001408, 0x01001008, 0x01001408,
|
1195 |
-
0x00001008, 0x00001408, 0x01001008, 0x01001408,
|
1196 |
-
0x00001108, 0x00001508, 0x01001108, 0x01001508,
|
1197 |
-
0x00001108, 0x00001508, 0x01001108, 0x01001508,
|
1198 |
-
0x10001008, 0x10001408, 0x11001008, 0x11001408,
|
1199 |
-
0x10001008, 0x10001408, 0x11001008, 0x11001408,
|
1200 |
-
0x10001108, 0x10001508, 0x11001108, 0x11001508,
|
1201 |
-
0x10001108, 0x10001508, 0x11001108, 0x11001508,
|
1202 |
-
0x00081008, 0x00081408, 0x01081008, 0x01081408,
|
1203 |
-
0x00081008, 0x00081408, 0x01081008, 0x01081408,
|
1204 |
-
0x00081108, 0x00081508, 0x01081108, 0x01081508,
|
1205 |
-
0x00081108, 0x00081508, 0x01081108, 0x01081508,
|
1206 |
-
0x10081008, 0x10081408, 0x11081008, 0x11081408,
|
1207 |
-
0x10081008, 0x10081408, 0x11081008, 0x11081408,
|
1208 |
-
0x10081108, 0x10081508, 0x11081108, 0x11081508,
|
1209 |
-
0x10081108, 0x10081508, 0x11081108, 0x11081508
|
1210 |
-
);
|
1211 |
-
|
1212 |
-
$keys = array();
|
1213 |
-
for ($des_round = 0; $des_round < $this->des_rounds; ++$des_round) {
|
1214 |
-
// pad the key and remove extra characters as appropriate.
|
1215 |
-
$key = str_pad(substr($this->key, $des_round * 8, 8), 8, "\0");
|
1216 |
-
|
1217 |
-
// Perform the PC/1 transformation and compute C and D.
|
1218 |
-
$t = unpack('Nl/Nr', $key);
|
1219 |
-
list($l, $r) = array($t['l'], $t['r']);
|
1220 |
-
$key = ($this->shuffle[$pc1map[ $r & 0xFF]] & "\x80\x80\x80\x80\x80\x80\x80\x00") |
|
1221 |
-
($this->shuffle[$pc1map[($r >> 8) & 0xFF]] & "\x40\x40\x40\x40\x40\x40\x40\x00") |
|
1222 |
-
($this->shuffle[$pc1map[($r >> 16) & 0xFF]] & "\x20\x20\x20\x20\x20\x20\x20\x00") |
|
1223 |
-
($this->shuffle[$pc1map[($r >> 24) & 0xFF]] & "\x10\x10\x10\x10\x10\x10\x10\x00") |
|
1224 |
-
($this->shuffle[$pc1map[ $l & 0xFF]] & "\x08\x08\x08\x08\x08\x08\x08\x00") |
|
1225 |
-
($this->shuffle[$pc1map[($l >> 8) & 0xFF]] & "\x04\x04\x04\x04\x04\x04\x04\x00") |
|
1226 |
-
($this->shuffle[$pc1map[($l >> 16) & 0xFF]] & "\x02\x02\x02\x02\x02\x02\x02\x00") |
|
1227 |
-
($this->shuffle[$pc1map[($l >> 24) & 0xFF]] & "\x01\x01\x01\x01\x01\x01\x01\x00");
|
1228 |
-
$key = unpack('Nc/Nd', $key);
|
1229 |
-
$c = ( $key['c'] >> 4) & 0x0FFFFFFF;
|
1230 |
-
$d = (($key['d'] >> 4) & 0x0FFFFFF0) | ($key['c'] & 0x0F);
|
1231 |
-
|
1232 |
-
$keys[$des_round] = array(
|
1233 |
-
self::ENCRYPT => array(),
|
1234 |
-
self::DECRYPT => array_fill(0, 32, 0)
|
1235 |
-
);
|
1236 |
-
for ($i = 0, $ki = 31; $i < 16; ++$i, $ki-= 2) {
|
1237 |
-
$c <<= $shifts[$i];
|
1238 |
-
$c = ($c | ($c >> 28)) & 0x0FFFFFFF;
|
1239 |
-
$d <<= $shifts[$i];
|
1240 |
-
$d = ($d | ($d >> 28)) & 0x0FFFFFFF;
|
1241 |
-
|
1242 |
-
// Perform the PC-2 transformation.
|
1243 |
-
$cp = $pc2mapc1[ $c >> 24 ] | $pc2mapc2[($c >> 16) & 0xFF] |
|
1244 |
-
$pc2mapc3[($c >> 8) & 0xFF] | $pc2mapc4[ $c & 0xFF];
|
1245 |
-
$dp = $pc2mapd1[ $d >> 24 ] | $pc2mapd2[($d >> 16) & 0xFF] |
|
1246 |
-
$pc2mapd3[($d >> 8) & 0xFF] | $pc2mapd4[ $d & 0xFF];
|
1247 |
-
|
1248 |
-
// Reorder: odd bytes/even bytes. Push the result in key schedule.
|
1249 |
-
$val1 = ( $cp & 0xFF000000) | (($cp << 8) & 0x00FF0000) |
|
1250 |
-
(($dp >> 16) & 0x0000FF00) | (($dp >> 8) & 0x000000FF);
|
1251 |
-
$val2 = (($cp << 8) & 0xFF000000) | (($cp << 16) & 0x00FF0000) |
|
1252 |
-
(($dp >> 8) & 0x0000FF00) | ( $dp & 0x000000FF);
|
1253 |
-
$keys[$des_round][self::ENCRYPT][ ] = $val1;
|
1254 |
-
$keys[$des_round][self::DECRYPT][$ki - 1] = $val1;
|
1255 |
-
$keys[$des_round][self::ENCRYPT][ ] = $val2;
|
1256 |
-
$keys[$des_round][self::DECRYPT][$ki ] = $val2;
|
1257 |
-
}
|
1258 |
-
}
|
1259 |
-
|
1260 |
-
switch ($this->des_rounds) {
|
1261 |
-
case 3: // 3DES keys
|
1262 |
-
$this->keys = array(
|
1263 |
-
self::ENCRYPT => array_merge(
|
1264 |
-
$keys[0][self::ENCRYPT],
|
1265 |
-
$keys[1][self::DECRYPT],
|
1266 |
-
$keys[2][self::ENCRYPT]
|
1267 |
-
),
|
1268 |
-
self::DECRYPT => array_merge(
|
1269 |
-
$keys[2][self::DECRYPT],
|
1270 |
-
$keys[1][self::ENCRYPT],
|
1271 |
-
$keys[0][self::DECRYPT]
|
1272 |
-
)
|
1273 |
-
);
|
1274 |
-
break;
|
1275 |
-
// case 1: // DES keys
|
1276 |
-
default:
|
1277 |
-
$this->keys = array(
|
1278 |
-
self::ENCRYPT => $keys[0][self::ENCRYPT],
|
1279 |
-
self::DECRYPT => $keys[0][self::DECRYPT]
|
1280 |
-
);
|
1281 |
-
}
|
1282 |
-
}
|
1283 |
-
|
1284 |
-
/**
|
1285 |
-
* Setup the performance-optimized function for de/encrypt()
|
1286 |
-
*
|
1287 |
-
* @see \phpseclib\Crypt\Base::_setupInlineCrypt()
|
1288 |
-
* @access private
|
1289 |
-
*/
|
1290 |
-
function _setupInlineCrypt()
|
1291 |
-
{
|
1292 |
-
$lambda_functions =& self::_getLambdaFunctions();
|
1293 |
-
|
1294 |
-
// Engine configuration for:
|
1295 |
-
// - DES ($des_rounds == 1) or
|
1296 |
-
// - 3DES ($des_rounds == 3)
|
1297 |
-
$des_rounds = $this->des_rounds;
|
1298 |
-
|
1299 |
-
// We create max. 10 hi-optimized code for memory reason. Means: For each $key one ultra fast inline-crypt function.
|
1300 |
-
// (Currently, for DES, one generated $lambda_function cost on php5.5@32bit ~135kb unfreeable mem and ~230kb on php5.5@64bit)
|
1301 |
-
// (Currently, for TripleDES, one generated $lambda_function cost on php5.5@32bit ~240kb unfreeable mem and ~340kb on php5.5@64bit)
|
1302 |
-
// After that, we'll still create very fast optimized code but not the hi-ultimative code, for each $mode one
|
1303 |
-
$gen_hi_opt_code = (bool)( count($lambda_functions) < 10 );
|
1304 |
-
|
1305 |
-
// Generation of a unique hash for our generated code
|
1306 |
-
$code_hash = "Crypt_DES, $des_rounds, {$this->mode}";
|
1307 |
-
if ($gen_hi_opt_code) {
|
1308 |
-
// For hi-optimized code, we create for each combination of
|
1309 |
-
// $mode, $des_rounds and $this->key its own encrypt/decrypt function.
|
1310 |
-
// After max 10 hi-optimized functions, we create generic
|
1311 |
-
// (still very fast.. but not ultra) functions for each $mode/$des_rounds
|
1312 |
-
// Currently 2 * 5 generic functions will be then max. possible.
|
1313 |
-
$code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
|
1314 |
-
}
|
1315 |
-
|
1316 |
-
// Is there a re-usable $lambda_functions in there? If not, we have to create it.
|
1317 |
-
if (!isset($lambda_functions[$code_hash])) {
|
1318 |
-
// Init code for both, encrypt and decrypt.
|
1319 |
-
$init_crypt = 'static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip;
|
1320 |
-
if (!$sbox1) {
|
1321 |
-
$sbox1 = array_map("intval", $self->sbox1);
|
1322 |
-
$sbox2 = array_map("intval", $self->sbox2);
|
1323 |
-
$sbox3 = array_map("intval", $self->sbox3);
|
1324 |
-
$sbox4 = array_map("intval", $self->sbox4);
|
1325 |
-
$sbox5 = array_map("intval", $self->sbox5);
|
1326 |
-
$sbox6 = array_map("intval", $self->sbox6);
|
1327 |
-
$sbox7 = array_map("intval", $self->sbox7);
|
1328 |
-
$sbox8 = array_map("intval", $self->sbox8);'
|
1329 |
-
/* Merge $shuffle with $[inv]ipmap */ . '
|
1330 |
-
for ($i = 0; $i < 256; ++$i) {
|
1331 |
-
$shuffleip[] = $self->shuffle[$self->ipmap[$i]];
|
1332 |
-
$shuffleinvip[] = $self->shuffle[$self->invipmap[$i]];
|
1333 |
-
}
|
1334 |
-
}
|
1335 |
-
';
|
1336 |
-
|
1337 |
-
switch (true) {
|
1338 |
-
case $gen_hi_opt_code:
|
1339 |
-
// In Hi-optimized code mode, we use our [3]DES key schedule as hardcoded integers.
|
1340 |
-
// No futher initialisation of the $keys schedule is necessary.
|
1341 |
-
// That is the extra performance boost.
|
1342 |
-
$k = array(
|
1343 |
-
self::ENCRYPT => $this->keys[self::ENCRYPT],
|
1344 |
-
self::DECRYPT => $this->keys[self::DECRYPT]
|
1345 |
-
);
|
1346 |
-
$init_encrypt = '';
|
1347 |
-
$init_decrypt = '';
|
1348 |
-
break;
|
1349 |
-
default:
|
1350 |
-
// In generic optimized code mode, we have to use, as the best compromise [currently],
|
1351 |
-
// our key schedule as $ke/$kd arrays. (with hardcoded indexes...)
|
1352 |
-
$k = array(
|
1353 |
-
self::ENCRYPT => array(),
|
1354 |
-
self::DECRYPT => array()
|
1355 |
-
);
|
1356 |
-
for ($i = 0, $c = count($this->keys[self::ENCRYPT]); $i < $c; ++$i) {
|
1357 |
-
$k[self::ENCRYPT][$i] = '$ke[' . $i . ']';
|
1358 |
-
$k[self::DECRYPT][$i] = '$kd[' . $i . ']';
|
1359 |
-
}
|
1360 |
-
$init_encrypt = '$ke = $self->keys[$self::ENCRYPT];';
|
1361 |
-
$init_decrypt = '$kd = $self->keys[$self::DECRYPT];';
|
1362 |
-
break;
|
1363 |
-
}
|
1364 |
-
|
1365 |
-
// Creating code for en- and decryption.
|
1366 |
-
$crypt_block = array();
|
1367 |
-
foreach (array(self::ENCRYPT, self::DECRYPT) as $c) {
|
1368 |
-
/* Do the initial IP permutation. */
|
1369 |
-
$crypt_block[$c] = '
|
1370 |
-
$in = unpack("N*", $in);
|
1371 |
-
$l = $in[1];
|
1372 |
-
$r = $in[2];
|
1373 |
-
$in = unpack("N*",
|
1374 |
-
($shuffleip[ $r & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") |
|
1375 |
-
($shuffleip[($r >> 8) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") |
|
1376 |
-
($shuffleip[($r >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") |
|
1377 |
-
($shuffleip[($r >> 24) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") |
|
1378 |
-
($shuffleip[ $l & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") |
|
1379 |
-
($shuffleip[($l >> 8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") |
|
1380 |
-
($shuffleip[($l >> 16) & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") |
|
1381 |
-
($shuffleip[($l >> 24) & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01")
|
1382 |
-
);
|
1383 |
-
' . /* Extract L0 and R0 */ '
|
1384 |
-
$l = $in[1];
|
1385 |
-
$r = $in[2];
|
1386 |
-
';
|
1387 |
-
|
1388 |
-
$l = '$l';
|
1389 |
-
$r = '$r';
|
1390 |
-
|
1391 |
-
// Perform DES or 3DES.
|
1392 |
-
for ($ki = -1, $des_round = 0; $des_round < $des_rounds; ++$des_round) {
|
1393 |
-
// Perform the 16 steps.
|
1394 |
-
for ($i = 0; $i < 16; ++$i) {
|
1395 |
-
// start of "the Feistel (F) function" - see the following URL:
|
1396 |
-
// http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png
|
1397 |
-
// Merge key schedule.
|
1398 |
-
$crypt_block[$c].= '
|
1399 |
-
$b1 = ((' . $r . ' >> 3) & 0x1FFFFFFF) ^ (' . $r . ' << 29) ^ ' . $k[$c][++$ki] . ';
|
1400 |
-
$b2 = ((' . $r . ' >> 31) & 0x00000001) ^ (' . $r . ' << 1) ^ ' . $k[$c][++$ki] . ';' .
|
1401 |
-
/* S-box indexing. */
|
1402 |
-
$l . ' = $sbox1[($b1 >> 24) & 0x3F] ^ $sbox2[($b2 >> 24) & 0x3F] ^
|
1403 |
-
$sbox3[($b1 >> 16) & 0x3F] ^ $sbox4[($b2 >> 16) & 0x3F] ^
|
1404 |
-
$sbox5[($b1 >> 8) & 0x3F] ^ $sbox6[($b2 >> 8) & 0x3F] ^
|
1405 |
-
$sbox7[ $b1 & 0x3F] ^ $sbox8[ $b2 & 0x3F] ^ ' . $l . ';
|
1406 |
-
';
|
1407 |
-
// end of "the Feistel (F) function"
|
1408 |
-
|
1409 |
-
// swap L & R
|
1410 |
-
list($l, $r) = array($r, $l);
|
1411 |
-
}
|
1412 |
-
list($l, $r) = array($r, $l);
|
1413 |
-
}
|
1414 |
-
|
1415 |
-
// Perform the inverse IP permutation.
|
1416 |
-
$crypt_block[$c].= '$in =
|
1417 |
-
($shuffleinvip[($l >> 24) & 0xFF] & "\x80\x80\x80\x80\x80\x80\x80\x80") |
|
1418 |
-
($shuffleinvip[($r >> 24) & 0xFF] & "\x40\x40\x40\x40\x40\x40\x40\x40") |
|
1419 |
-
($shuffleinvip[($l >> 16) & 0xFF] & "\x20\x20\x20\x20\x20\x20\x20\x20") |
|
1420 |
-
($shuffleinvip[($r >> 16) & 0xFF] & "\x10\x10\x10\x10\x10\x10\x10\x10") |
|
1421 |
-
($shuffleinvip[($l >> 8) & 0xFF] & "\x08\x08\x08\x08\x08\x08\x08\x08") |
|
1422 |
-
($shuffleinvip[($r >> 8) & 0xFF] & "\x04\x04\x04\x04\x04\x04\x04\x04") |
|
1423 |
-
($shuffleinvip[ $l & 0xFF] & "\x02\x02\x02\x02\x02\x02\x02\x02") |
|
1424 |
-
($shuffleinvip[ $r & 0xFF] & "\x01\x01\x01\x01\x01\x01\x01\x01");
|
1425 |
-
';
|
1426 |
-
}
|
1427 |
-
|
1428 |
-
// Creates the inline-crypt function
|
1429 |
-
$lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
|
1430 |
-
array(
|
1431 |
-
'init_crypt' => $init_crypt,
|
1432 |
-
'init_encrypt' => $init_encrypt,
|
1433 |
-
'init_decrypt' => $init_decrypt,
|
1434 |
-
'encrypt_block' => $crypt_block[self::ENCRYPT],
|
1435 |
-
'decrypt_block' => $crypt_block[self::DECRYPT]
|
1436 |
-
)
|
1437 |
-
);
|
1438 |
-
}
|
1439 |
-
|
1440 |
-
// Set the inline-crypt function as callback in: $this->inline_crypt
|
1441 |
-
$this->inline_crypt = $lambda_functions[$code_hash];
|
1442 |
-
}
|
1443 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/phpseclib/phpseclib/phpseclib/Crypt/Hash.php
DELETED
@@ -1,824 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
|
5 |
-
*
|
6 |
-
* Uses hash() or mhash() if available and an internal implementation, otherwise. Currently supports the following:
|
7 |
-
*
|
8 |
-
* md2, md5, md5-96, sha1, sha1-96, sha256, sha256-96, sha384, and sha512, sha512-96
|
9 |
-
*
|
10 |
-
* If {@link self::setKey() setKey()} is called, {@link self::hash() hash()} will return the HMAC as opposed to
|
11 |
-
* the hash. If no valid algorithm is provided, sha1 will be used.
|
12 |
-
*
|
13 |
-
* PHP version 5
|
14 |
-
*
|
15 |
-
* {@internal The variable names are the same as those in
|
16 |
-
* {@link http://tools.ietf.org/html/rfc2104#section-2 RFC2104}.}}
|
17 |
-
*
|
18 |
-
* Here's a short example of how to use this library:
|
19 |
-
* <code>
|
20 |
-
* <?php
|
21 |
-
* include 'vendor/autoload.php';
|
22 |
-
*
|
23 |
-
* $hash = new \phpseclib\Crypt\Hash('sha1');
|
24 |
-
*
|
25 |
-
* $hash->setKey('abcdefg');
|
26 |
-
*
|
27 |
-
* echo base64_encode($hash->hash('abcdefg'));
|
28 |
-
* ?>
|
29 |
-
* </code>
|
30 |
-
*
|
31 |
-
* @category Crypt
|
32 |
-
* @package Hash
|
33 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
34 |
-
* @copyright 2007 Jim Wigginton
|
35 |
-
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
36 |
-
* @link http://phpseclib.sourceforge.net
|
37 |
-
*/
|
38 |
-
|
39 |
-
namespace phpseclib\Crypt;
|
40 |
-
|
41 |
-
use phpseclib\Math\BigInteger;
|
42 |
-
|
43 |
-
/**
|
44 |
-
* Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
|
45 |
-
*
|
46 |
-
* @package Hash
|
47 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
48 |
-
* @access public
|
49 |
-
*/
|
50 |
-
class Hash
|
51 |
-
{
|
52 |
-
/**#@+
|
53 |
-
* @access private
|
54 |
-
* @see \phpseclib\Crypt\Hash::__construct()
|
55 |
-
*/
|
56 |
-
/**
|
57 |
-
* Toggles the internal implementation
|
58 |
-
*/
|
59 |
-
const MODE_INTERNAL = 1;
|
60 |
-
/**
|
61 |
-
* Toggles the mhash() implementation, which has been deprecated on PHP 5.3.0+.
|
62 |
-
*/
|
63 |
-
const MODE_MHASH = 2;
|
64 |
-
/**
|
65 |
-
* Toggles the hash() implementation, which works on PHP 5.1.2+.
|
66 |
-
*/
|
67 |
-
const MODE_HASH = 3;
|
68 |
-
/**#@-*/
|
69 |
-
|
70 |
-
/**
|
71 |
-
* Hash Parameter
|
72 |
-
*
|
73 |
-
* @see self::setHash()
|
74 |
-
* @var int
|
75 |
-
* @access private
|
76 |
-
*/
|
77 |
-
var $hashParam;
|
78 |
-
|
79 |
-
/**
|
80 |
-
* Byte-length of compression blocks / key (Internal HMAC)
|
81 |
-
*
|
82 |
-
* @see self::setAlgorithm()
|
83 |
-
* @var int
|
84 |
-
* @access private
|
85 |
-
*/
|
86 |
-
var $b;
|
87 |
-
|
88 |
-
/**
|
89 |
-
* Byte-length of hash output (Internal HMAC)
|
90 |
-
*
|
91 |
-
* @see self::setHash()
|
92 |
-
* @var int
|
93 |
-
* @access private
|
94 |
-
*/
|
95 |
-
var $l = false;
|
96 |
-
|
97 |
-
/**
|
98 |
-
* Hash Algorithm
|
99 |
-
*
|
100 |
-
* @see self::setHash()
|
101 |
-
* @var string
|
102 |
-
* @access private
|
103 |
-
*/
|
104 |
-
var $hash;
|
105 |
-
|
106 |
-
/**
|
107 |
-
* Key
|
108 |
-
*
|
109 |
-
* @see self::setKey()
|
110 |
-
* @var string
|
111 |
-
* @access private
|
112 |
-
*/
|
113 |
-
var $key = false;
|
114 |
-
|
115 |
-
/**
|
116 |
-
* Outer XOR (Internal HMAC)
|
117 |
-
*
|
118 |
-
* @see self::setKey()
|
119 |
-
* @var string
|
120 |
-
* @access private
|
121 |
-
*/
|
122 |
-
var $opad;
|
123 |
-
|
124 |
-
/**
|
125 |
-
* Inner XOR (Internal HMAC)
|
126 |
-
*
|
127 |
-
* @see self::setKey()
|
128 |
-
* @var string
|
129 |
-
* @access private
|
130 |
-
*/
|
131 |
-
var $ipad;
|
132 |
-
|
133 |
-
/**
|
134 |
-
* Default Constructor.
|
135 |
-
*
|
136 |
-
* @param string $hash
|
137 |
-
* @return \phpseclib\Crypt\Hash
|
138 |
-
* @access public
|
139 |
-
*/
|
140 |
-
function __construct($hash = 'sha1')
|
141 |
-
{
|
142 |
-
if (!defined('CRYPT_HASH_MODE')) {
|
143 |
-
switch (true) {
|
144 |
-
case extension_loaded('hash'):
|
145 |
-
define('CRYPT_HASH_MODE', self::MODE_HASH);
|
146 |
-
break;
|
147 |
-
case extension_loaded('mhash'):
|
148 |
-
define('CRYPT_HASH_MODE', self::MODE_MHASH);
|
149 |
-
break;
|
150 |
-
default:
|
151 |
-
define('CRYPT_HASH_MODE', self::MODE_INTERNAL);
|
152 |
-
}
|
153 |
-
}
|
154 |
-
|
155 |
-
$this->setHash($hash);
|
156 |
-
}
|
157 |
-
|
158 |
-
/**
|
159 |
-
* Sets the key for HMACs
|
160 |
-
*
|
161 |
-
* Keys can be of any length.
|
162 |
-
*
|
163 |
-
* @access public
|
164 |
-
* @param string $key
|
165 |
-
*/
|
166 |
-
function setKey($key = false)
|
167 |
-
{
|
168 |
-
$this->key = $key;
|
169 |
-
}
|
170 |
-
|
171 |
-
/**
|
172 |
-
* Gets the hash function.
|
173 |
-
*
|
174 |
-
* As set by the constructor or by the setHash() method.
|
175 |
-
*
|
176 |
-
* @access public
|
177 |
-
* @return string
|
178 |
-
*/
|
179 |
-
function getHash()
|
180 |
-
{
|
181 |
-
return $this->hashParam;
|
182 |
-
}
|
183 |
-
|
184 |
-
/**
|
185 |
-
* Sets the hash function.
|
186 |
-
*
|
187 |
-
* @access public
|
188 |
-
* @param string $hash
|
189 |
-
*/
|
190 |
-
function setHash($hash)
|
191 |
-
{
|
192 |
-
$this->hashParam = $hash = strtolower($hash);
|
193 |
-
switch ($hash) {
|
194 |
-
case 'md5-96':
|
195 |
-
case 'sha1-96':
|
196 |
-
case 'sha256-96':
|
197 |
-
case 'sha512-96':
|
198 |
-
$hash = substr($hash, 0, -3);
|
199 |
-
$this->l = 12; // 96 / 8 = 12
|
200 |
-
break;
|
201 |
-
case 'md2':
|
202 |
-
case 'md5':
|
203 |
-
$this->l = 16;
|
204 |
-
break;
|
205 |
-
case 'sha1':
|
206 |
-
$this->l = 20;
|
207 |
-
break;
|
208 |
-
case 'sha256':
|
209 |
-
$this->l = 32;
|
210 |
-
break;
|
211 |
-
case 'sha384':
|
212 |
-
$this->l = 48;
|
213 |
-
break;
|
214 |
-
case 'sha512':
|
215 |
-
$this->l = 64;
|
216 |
-
}
|
217 |
-
|
218 |
-
switch ($hash) {
|
219 |
-
case 'md2':
|
220 |
-
$mode = CRYPT_HASH_MODE == self::MODE_HASH && in_array('md2', hash_algos()) ?
|
221 |
-
self::MODE_HASH : self::MODE_INTERNAL;
|
222 |
-
break;
|
223 |
-
case 'sha384':
|
224 |
-
case 'sha512':
|
225 |
-
$mode = CRYPT_HASH_MODE == self::MODE_MHASH ? self::MODE_INTERNAL : CRYPT_HASH_MODE;
|
226 |
-
break;
|
227 |
-
default:
|
228 |
-
$mode = CRYPT_HASH_MODE;
|
229 |
-
}
|
230 |
-
|
231 |
-
switch ($mode) {
|
232 |
-
case self::MODE_MHASH:
|
233 |
-
switch ($hash) {
|
234 |
-
case 'md5':
|
235 |
-
$this->hash = MHASH_MD5;
|
236 |
-
break;
|
237 |
-
case 'sha256':
|
238 |
-
$this->hash = MHASH_SHA256;
|
239 |
-
break;
|
240 |
-
case 'sha1':
|
241 |
-
default:
|
242 |
-
$this->hash = MHASH_SHA1;
|
243 |
-
}
|
244 |
-
return;
|
245 |
-
case self::MODE_HASH:
|
246 |
-
switch ($hash) {
|
247 |
-
case 'md5':
|
248 |
-
$this->hash = 'md5';
|
249 |
-
return;
|
250 |
-
case 'md2':
|
251 |
-
case 'sha256':
|
252 |
-
case 'sha384':
|
253 |
-
case 'sha512':
|
254 |
-
$this->hash = $hash;
|
255 |
-
return;
|
256 |
-
case 'sha1':
|
257 |
-
default:
|
258 |
-
$this->hash = 'sha1';
|
259 |
-
}
|
260 |
-
return;
|
261 |
-
}
|
262 |
-
|
263 |
-
switch ($hash) {
|
264 |
-
case 'md2':
|
265 |
-
$this->b = 16;
|
266 |
-
$this->hash = array($this, '_md2');
|
267 |
-
break;
|
268 |
-
case 'md5':
|
269 |
-
$this->b = 64;
|
270 |
-
$this->hash = array($this, '_md5');
|
271 |
-
break;
|
272 |
-
case 'sha256':
|
273 |
-
$this->b = 64;
|
274 |
-
$this->hash = array($this, '_sha256');
|
275 |
-
break;
|
276 |
-
case 'sha384':
|
277 |
-
case 'sha512':
|
278 |
-
$this->b = 128;
|
279 |
-
$this->hash = array($this, '_sha512');
|
280 |
-
break;
|
281 |
-
case 'sha1':
|
282 |
-
default:
|
283 |
-
$this->b = 64;
|
284 |
-
$this->hash = array($this, '_sha1');
|
285 |
-
}
|
286 |
-
|
287 |
-
$this->ipad = str_repeat(chr(0x36), $this->b);
|
288 |
-
$this->opad = str_repeat(chr(0x5C), $this->b);
|
289 |
-
}
|
290 |
-
|
291 |
-
/**
|
292 |
-
* Compute the HMAC.
|
293 |
-
*
|
294 |
-
* @access public
|
295 |
-
* @param string $text
|
296 |
-
* @return string
|
297 |
-
*/
|
298 |
-
function hash($text)
|
299 |
-
{
|
300 |
-
$mode = is_array($this->hash) ? self::MODE_INTERNAL : CRYPT_HASH_MODE;
|
301 |
-
|
302 |
-
if (!empty($this->key) || is_string($this->key)) {
|
303 |
-
switch ($mode) {
|
304 |
-
case self::MODE_MHASH:
|
305 |
-
$output = mhash($this->hash, $text, $this->key);
|
306 |
-
break;
|
307 |
-
case self::MODE_HASH:
|
308 |
-
$output = hash_hmac($this->hash, $text, $this->key, true);
|
309 |
-
break;
|
310 |
-
case self::MODE_INTERNAL:
|
311 |
-
/* "Applications that use keys longer than B bytes will first hash the key using H and then use the
|
312 |
-
resultant L byte string as the actual key to HMAC."
|
313 |
-
|
314 |
-
-- http://tools.ietf.org/html/rfc2104#section-2 */
|
315 |
-
$key = strlen($this->key) > $this->b ? call_user_func($this->hash, $this->key) : $this->key;
|
316 |
-
|
317 |
-
$key = str_pad($key, $this->b, chr(0)); // step 1
|
318 |
-
$temp = $this->ipad ^ $key; // step 2
|
319 |
-
$temp .= $text; // step 3
|
320 |
-
$temp = call_user_func($this->hash, $temp); // step 4
|
321 |
-
$output = $this->opad ^ $key; // step 5
|
322 |
-
$output.= $temp; // step 6
|
323 |
-
$output = call_user_func($this->hash, $output); // step 7
|
324 |
-
}
|
325 |
-
} else {
|
326 |
-
switch ($mode) {
|
327 |
-
case self::MODE_MHASH:
|
328 |
-
$output = mhash($this->hash, $text);
|
329 |
-
break;
|
330 |
-
case self::MODE_HASH:
|
331 |
-
$output = hash($this->hash, $text, true);
|
332 |
-
break;
|
333 |
-
case self::MODE_INTERNAL:
|
334 |
-
$output = call_user_func($this->hash, $text);
|
335 |
-
}
|
336 |
-
}
|
337 |
-
|
338 |
-
return substr($output, 0, $this->l);
|
339 |
-
}
|
340 |
-
|
341 |
-
/**
|
342 |
-
* Returns the hash length (in bytes)
|
343 |
-
*
|
344 |
-
* @access public
|
345 |
-
* @return int
|
346 |
-
*/
|
347 |
-
function getLength()
|
348 |
-
{
|
349 |
-
return $this->l;
|
350 |
-
}
|
351 |
-
|
352 |
-
/**
|
353 |
-
* Wrapper for MD5
|
354 |
-
*
|
355 |
-
* @access private
|
356 |
-
* @param string $m
|
357 |
-
*/
|
358 |
-
function _md5($m)
|
359 |
-
{
|
360 |
-
return pack('H*', md5($m));
|
361 |
-
}
|
362 |
-
|
363 |
-
/**
|
364 |
-
* Wrapper for SHA1
|
365 |
-
*
|
366 |
-
* @access private
|
367 |
-
* @param string $m
|
368 |
-
*/
|
369 |
-
function _sha1($m)
|
370 |
-
{
|
371 |
-
return pack('H*', sha1($m));
|
372 |
-
}
|
373 |
-
|
374 |
-
/**
|
375 |
-
* Pure-PHP implementation of MD2
|
376 |
-
*
|
377 |
-
* See {@link http://tools.ietf.org/html/rfc1319 RFC1319}.
|
378 |
-
*
|
379 |
-
* @access private
|
380 |
-
* @param string $m
|
381 |
-
*/
|
382 |
-
function _md2($m)
|
383 |
-
{
|
384 |
-
static $s = array(
|
385 |
-
41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
|
386 |
-
19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
|
387 |
-
76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
|
388 |
-
138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
|
389 |
-
245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
|
390 |
-
148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
|
391 |
-
39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
|
392 |
-
181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
|
393 |
-
150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
|
394 |
-
112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
|
395 |
-
96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
|
396 |
-
85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
|
397 |
-
234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
|
398 |
-
129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
|
399 |
-
8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
|
400 |
-
203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
|
401 |
-
166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
|
402 |
-
31, 26, 219, 153, 141, 51, 159, 17, 131, 20
|
403 |
-
);
|
404 |
-
|
405 |
-
// Step 1. Append Padding Bytes
|
406 |
-
$pad = 16 - (strlen($m) & 0xF);
|
407 |
-
$m.= str_repeat(chr($pad), $pad);
|
408 |
-
|
409 |
-
$length = strlen($m);
|
410 |
-
|
411 |
-
// Step 2. Append Checksum
|
412 |
-
$c = str_repeat(chr(0), 16);
|
413 |
-
$l = chr(0);
|
414 |
-
for ($i = 0; $i < $length; $i+= 16) {
|
415 |
-
for ($j = 0; $j < 16; $j++) {
|
416 |
-
// RFC1319 incorrectly states that C[j] should be set to S[c xor L]
|
417 |
-
//$c[$j] = chr($s[ord($m[$i + $j] ^ $l)]);
|
418 |
-
// per <http://www.rfc-editor.org/errata_search.php?rfc=1319>, however, C[j] should be set to S[c xor L] xor C[j]
|
419 |
-
$c[$j] = chr($s[ord($m[$i + $j] ^ $l)] ^ ord($c[$j]));
|
420 |
-
$l = $c[$j];
|
421 |
-
}
|
422 |
-
}
|
423 |
-
$m.= $c;
|
424 |
-
|
425 |
-
$length+= 16;
|
426 |
-
|
427 |
-
// Step 3. Initialize MD Buffer
|
428 |
-
$x = str_repeat(chr(0), 48);
|
429 |
-
|
430 |
-
// Step 4. Process Message in 16-Byte Blocks
|
431 |
-
for ($i = 0; $i < $length; $i+= 16) {
|
432 |
-
for ($j = 0; $j < 16; $j++) {
|
433 |
-
$x[$j + 16] = $m[$i + $j];
|
434 |
-
$x[$j + 32] = $x[$j + 16] ^ $x[$j];
|
435 |
-
}
|
436 |
-
$t = chr(0);
|
437 |
-
for ($j = 0; $j < 18; $j++) {
|
438 |
-
for ($k = 0; $k < 48; $k++) {
|
439 |
-
$x[$k] = $t = $x[$k] ^ chr($s[ord($t)]);
|
440 |
-
//$t = $x[$k] = $x[$k] ^ chr($s[ord($t)]);
|
441 |
-
}
|
442 |
-
$t = chr(ord($t) + $j);
|
443 |
-
}
|
444 |
-
}
|
445 |
-
|
446 |
-
// Step 5. Output
|
447 |
-
return substr($x, 0, 16);
|
448 |
-
}
|
449 |
-
|
450 |
-
/**
|
451 |
-
* Pure-PHP implementation of SHA256
|
452 |
-
*
|
453 |
-
* See {@link http://en.wikipedia.org/wiki/SHA_hash_functions#SHA-256_.28a_SHA-2_variant.29_pseudocode SHA-256 (a SHA-2 variant) pseudocode - Wikipedia}.
|
454 |
-
*
|
455 |
-
* @access private
|
456 |
-
* @param string $m
|
457 |
-
*/
|
458 |
-
function _sha256($m)
|
459 |
-
{
|
460 |
-
if (extension_loaded('suhosin')) {
|
461 |
-
return pack('H*', sha256($m));
|
462 |
-
}
|
463 |
-
|
464 |
-
// Initialize variables
|
465 |
-
$hash = array(
|
466 |
-
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
|
467 |
-
);
|
468 |
-
// Initialize table of round constants
|
469 |
-
// (first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311)
|
470 |
-
static $k = array(
|
471 |
-
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
472 |
-
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
473 |
-
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
474 |
-
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
475 |
-
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
476 |
-
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
477 |
-
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
478 |
-
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
479 |
-
);
|
480 |
-
|
481 |
-
// Pre-processing
|
482 |
-
$length = strlen($m);
|
483 |
-
// to round to nearest 56 mod 64, we'll add 64 - (length + (64 - 56)) % 64
|
484 |
-
$m.= str_repeat(chr(0), 64 - (($length + 8) & 0x3F));
|
485 |
-
$m[$length] = chr(0x80);
|
486 |
-
// we don't support hashing strings 512MB long
|
487 |
-
$m.= pack('N2', 0, $length << 3);
|
488 |
-
|
489 |
-
// Process the message in successive 512-bit chunks
|
490 |
-
$chunks = str_split($m, 64);
|
491 |
-
foreach ($chunks as $chunk) {
|
492 |
-
$w = array();
|
493 |
-
for ($i = 0; $i < 16; $i++) {
|
494 |
-
extract(unpack('Ntemp', $this->_string_shift($chunk, 4)));
|
495 |
-
$w[] = $temp;
|
496 |
-
}
|
497 |
-
|
498 |
-
// Extend the sixteen 32-bit words into sixty-four 32-bit words
|
499 |
-
for ($i = 16; $i < 64; $i++) {
|
500 |
-
// @codingStandardsIgnoreStart
|
501 |
-
$s0 = $this->_rightRotate($w[$i - 15], 7) ^
|
502 |
-
$this->_rightRotate($w[$i - 15], 18) ^
|
503 |
-
$this->_rightShift( $w[$i - 15], 3);
|
504 |
-
$s1 = $this->_rightRotate($w[$i - 2], 17) ^
|
505 |
-
$this->_rightRotate($w[$i - 2], 19) ^
|
506 |
-
$this->_rightShift( $w[$i - 2], 10);
|
507 |
-
// @codingStandardsIgnoreEnd
|
508 |
-
$w[$i] = $this->_add($w[$i - 16], $s0, $w[$i - 7], $s1);
|
509 |
-
}
|
510 |
-
|
511 |
-
// Initialize hash value for this chunk
|
512 |
-
list($a, $b, $c, $d, $e, $f, $g, $h) = $hash;
|
513 |
-
|
514 |
-
// Main loop
|
515 |
-
for ($i = 0; $i < 64; $i++) {
|
516 |
-
$s0 = $this->_rightRotate($a, 2) ^
|
517 |
-
$this->_rightRotate($a, 13) ^
|
518 |
-
$this->_rightRotate($a, 22);
|
519 |
-
$maj = ($a & $b) ^
|
520 |
-
($a & $c) ^
|
521 |
-
($b & $c);
|
522 |
-
$t2 = $this->_add($s0, $maj);
|
523 |
-
|
524 |
-
$s1 = $this->_rightRotate($e, 6) ^
|
525 |
-
$this->_rightRotate($e, 11) ^
|
526 |
-
$this->_rightRotate($e, 25);
|
527 |
-
$ch = ($e & $f) ^
|
528 |
-
($this->_not($e) & $g);
|
529 |
-
$t1 = $this->_add($h, $s1, $ch, $k[$i], $w[$i]);
|
530 |
-
|
531 |
-
$h = $g;
|
532 |
-
$g = $f;
|
533 |
-
$f = $e;
|
534 |
-
$e = $this->_add($d, $t1);
|
535 |
-
$d = $c;
|
536 |
-
$c = $b;
|
537 |
-
$b = $a;
|
538 |
-
$a = $this->_add($t1, $t2);
|
539 |
-
}
|
540 |
-
|
541 |
-
// Add this chunk's hash to result so far
|
542 |
-
$hash = array(
|
543 |
-
$this->_add($hash[0], $a),
|
544 |
-
$this->_add($hash[1], $b),
|
545 |
-
$this->_add($hash[2], $c),
|
546 |
-
$this->_add($hash[3], $d),
|
547 |
-
$this->_add($hash[4], $e),
|
548 |
-
$this->_add($hash[5], $f),
|
549 |
-
$this->_add($hash[6], $g),
|
550 |
-
$this->_add($hash[7], $h)
|
551 |
-
);
|
552 |
-
}
|
553 |
-
|
554 |
-
// Produce the final hash value (big-endian)
|
555 |
-
return pack('N8', $hash[0], $hash[1], $hash[2], $hash[3], $hash[4], $hash[5], $hash[6], $hash[7]);
|
556 |
-
}
|
557 |
-
|
558 |
-
/**
|
559 |
-
* Pure-PHP implementation of SHA384 and SHA512
|
560 |
-
*
|
561 |
-
* @access private
|
562 |
-
* @param string $m
|
563 |
-
*/
|
564 |
-
function _sha512($m)
|
565 |
-
{
|
566 |
-
static $init384, $init512, $k;
|
567 |
-
|
568 |
-
if (!isset($k)) {
|
569 |
-
// Initialize variables
|
570 |
-
$init384 = array( // initial values for SHA384
|
571 |
-
'cbbb9d5dc1059ed8', '629a292a367cd507', '9159015a3070dd17', '152fecd8f70e5939',
|
572 |
-
'67332667ffc00b31', '8eb44a8768581511', 'db0c2e0d64f98fa7', '47b5481dbefa4fa4'
|
573 |
-
);
|
574 |
-
$init512 = array( // initial values for SHA512
|
575 |
-
'6a09e667f3bcc908', 'bb67ae8584caa73b', '3c6ef372fe94f82b', 'a54ff53a5f1d36f1',
|
576 |
-
'510e527fade682d1', '9b05688c2b3e6c1f', '1f83d9abfb41bd6b', '5be0cd19137e2179'
|
577 |
-
);
|
578 |
-
|
579 |
-
for ($i = 0; $i < 8; $i++) {
|
580 |
-
$init384[$i] = new BigInteger($init384[$i], 16);
|
581 |
-
$init384[$i]->setPrecision(64);
|
582 |
-
$init512[$i] = new BigInteger($init512[$i], 16);
|
583 |
-
$init512[$i]->setPrecision(64);
|
584 |
-
}
|
585 |
-
|
586 |
-
// Initialize table of round constants
|
587 |
-
// (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409)
|
588 |
-
$k = array(
|
589 |
-
'428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc',
|
590 |
-
'3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118',
|
591 |
-
'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2',
|
592 |
-
'72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694',
|
593 |
-
'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65',
|
594 |
-
'2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5',
|
595 |
-
'983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4',
|
596 |
-
'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70',
|
597 |
-
'27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df',
|
598 |
-
'650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b',
|
599 |
-
'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30',
|
600 |
-
'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8',
|
601 |
-
'19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8',
|
602 |
-
'391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3',
|
603 |
-
'748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec',
|
604 |
-
'90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b',
|
605 |
-
'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178',
|
606 |
-
'06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b',
|
607 |
-
'28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c',
|
608 |
-
'4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817'
|
609 |
-
);
|
610 |
-
|
611 |
-
for ($i = 0; $i < 80; $i++) {
|
612 |
-
$k[$i] = new BigInteger($k[$i], 16);
|
613 |
-
}
|
614 |
-
}
|
615 |
-
|
616 |
-
$hash = $this->l == 48 ? $init384 : $init512;
|
617 |
-
|
618 |
-
// Pre-processing
|
619 |
-
$length = strlen($m);
|
620 |
-
// to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128
|
621 |
-
$m.= str_repeat(chr(0), 128 - (($length + 16) & 0x7F));
|
622 |
-
$m[$length] = chr(0x80);
|
623 |
-
// we don't support hashing strings 512MB long
|
624 |
-
$m.= pack('N4', 0, 0, 0, $length << 3);
|
625 |
-
|
626 |
-
// Process the message in successive 1024-bit chunks
|
627 |
-
$chunks = str_split($m, 128);
|
628 |
-
foreach ($chunks as $chunk) {
|
629 |
-
$w = array();
|
630 |
-
for ($i = 0; $i < 16; $i++) {
|
631 |
-
$temp = new BigInteger($this->_string_shift($chunk, 8), 256);
|
632 |
-
$temp->setPrecision(64);
|
633 |
-
$w[] = $temp;
|
634 |
-
}
|
635 |
-
|
636 |
-
// Extend the sixteen 32-bit words into eighty 32-bit words
|
637 |
-
for ($i = 16; $i < 80; $i++) {
|
638 |
-
$temp = array(
|
639 |
-
$w[$i - 15]->bitwise_rightRotate(1),
|
640 |
-
$w[$i - 15]->bitwise_rightRotate(8),
|
641 |
-
$w[$i - 15]->bitwise_rightShift(7)
|
642 |
-
);
|
643 |
-
$s0 = $temp[0]->bitwise_xor($temp[1]);
|
644 |
-
$s0 = $s0->bitwise_xor($temp[2]);
|
645 |
-
$temp = array(
|
646 |
-
$w[$i - 2]->bitwise_rightRotate(19),
|
647 |
-
$w[$i - 2]->bitwise_rightRotate(61),
|
648 |
-
$w[$i - 2]->bitwise_rightShift(6)
|
649 |
-
);
|
650 |
-
$s1 = $temp[0]->bitwise_xor($temp[1]);
|
651 |
-
$s1 = $s1->bitwise_xor($temp[2]);
|
652 |
-
$w[$i] = $w[$i - 16]->copy();
|
653 |
-
$w[$i] = $w[$i]->add($s0);
|
654 |
-
$w[$i] = $w[$i]->add($w[$i - 7]);
|
655 |
-
$w[$i] = $w[$i]->add($s1);
|
656 |
-
}
|
657 |
-
|
658 |
-
// Initialize hash value for this chunk
|
659 |
-
$a = $hash[0]->copy();
|
660 |
-
$b = $hash[1]->copy();
|
661 |
-
$c = $hash[2]->copy();
|
662 |
-
$d = $hash[3]->copy();
|
663 |
-
$e = $hash[4]->copy();
|
664 |
-
$f = $hash[5]->copy();
|
665 |
-
$g = $hash[6]->copy();
|
666 |
-
$h = $hash[7]->copy();
|
667 |
-
|
668 |
-
// Main loop
|
669 |
-
for ($i = 0; $i < 80; $i++) {
|
670 |
-
$temp = array(
|
671 |
-
$a->bitwise_rightRotate(28),
|
672 |
-
$a->bitwise_rightRotate(34),
|
673 |
-
$a->bitwise_rightRotate(39)
|
674 |
-
);
|
675 |
-
$s0 = $temp[0]->bitwise_xor($temp[1]);
|
676 |
-
$s0 = $s0->bitwise_xor($temp[2]);
|
677 |
-
$temp = array(
|
678 |
-
$a->bitwise_and($b),
|
679 |
-
$a->bitwise_and($c),
|
680 |
-
$b->bitwise_and($c)
|
681 |
-
);
|
682 |
-
$maj = $temp[0]->bitwise_xor($temp[1]);
|
683 |
-
$maj = $maj->bitwise_xor($temp[2]);
|
684 |
-
$t2 = $s0->add($maj);
|
685 |
-
|
686 |
-
$temp = array(
|
687 |
-
$e->bitwise_rightRotate(14),
|
688 |
-
$e->bitwise_rightRotate(18),
|
689 |
-
$e->bitwise_rightRotate(41)
|
690 |
-
);
|
691 |
-
$s1 = $temp[0]->bitwise_xor($temp[1]);
|
692 |
-
$s1 = $s1->bitwise_xor($temp[2]);
|
693 |
-
$temp = array(
|
694 |
-
$e->bitwise_and($f),
|
695 |
-
$g->bitwise_and($e->bitwise_not())
|
696 |
-
);
|
697 |
-
$ch = $temp[0]->bitwise_xor($temp[1]);
|
698 |
-
$t1 = $h->add($s1);
|
699 |
-
$t1 = $t1->add($ch);
|
700 |
-
$t1 = $t1->add($k[$i]);
|
701 |
-
$t1 = $t1->add($w[$i]);
|
702 |
-
|
703 |
-
$h = $g->copy();
|
704 |
-
$g = $f->copy();
|
705 |
-
$f = $e->copy();
|
706 |
-
$e = $d->add($t1);
|
707 |
-
$d = $c->copy();
|
708 |
-
$c = $b->copy();
|
709 |
-
$b = $a->copy();
|
710 |
-
$a = $t1->add($t2);
|
711 |
-
}
|
712 |
-
|
713 |
-
// Add this chunk's hash to result so far
|
714 |
-
$hash = array(
|
715 |
-
$hash[0]->add($a),
|
716 |
-
$hash[1]->add($b),
|
717 |
-
$hash[2]->add($c),
|
718 |
-
$hash[3]->add($d),
|
719 |
-
$hash[4]->add($e),
|
720 |
-
$hash[5]->add($f),
|
721 |
-
$hash[6]->add($g),
|
722 |
-
$hash[7]->add($h)
|
723 |
-
);
|
724 |
-
}
|
725 |
-
|
726 |
-
// Produce the final hash value (big-endian)
|
727 |
-
// (\phpseclib\Crypt\Hash::hash() trims the output for hashes but not for HMACs. as such, we trim the output here)
|
728 |
-
$temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() .
|
729 |
-
$hash[4]->toBytes() . $hash[5]->toBytes();
|
730 |
-
if ($this->l != 48) {
|
731 |
-
$temp.= $hash[6]->toBytes() . $hash[7]->toBytes();
|
732 |
-
}
|
733 |
-
|
734 |
-
return $temp;
|
735 |
-
}
|
736 |
-
|
737 |
-
/**
|
738 |
-
* Right Rotate
|
739 |
-
*
|
740 |
-
* @access private
|
741 |
-
* @param int $int
|
742 |
-
* @param int $amt
|
743 |
-
* @see self::_sha256()
|
744 |
-
* @return int
|
745 |
-
*/
|
746 |
-
function _rightRotate($int, $amt)
|
747 |
-
{
|
748 |
-
$invamt = 32 - $amt;
|
749 |
-
$mask = (1 << $invamt) - 1;
|
750 |
-
return (($int << $invamt) & 0xFFFFFFFF) | (($int >> $amt) & $mask);
|
751 |
-
}
|
752 |
-
|
753 |
-
/**
|
754 |
-
* Right Shift
|
755 |
-
*
|
756 |
-
* @access private
|
757 |
-
* @param int $int
|
758 |
-
* @param int $amt
|
759 |
-
* @see self::_sha256()
|
760 |
-
* @return int
|
761 |
-
*/
|
762 |
-
function _rightShift($int, $amt)
|
763 |
-
{
|
764 |
-
$mask = (1 << (32 - $amt)) - 1;
|
765 |
-
return ($int >> $amt) & $mask;
|
766 |
-
}
|
767 |
-
|
768 |
-
/**
|
769 |
-
* Not
|
770 |
-
*
|
771 |
-
* @access private
|
772 |
-
* @param int $int
|
773 |
-
* @see self::_sha256()
|
774 |
-
* @return int
|
775 |
-
*/
|
776 |
-
function _not($int)
|
777 |
-
{
|
778 |
-
return ~$int & 0xFFFFFFFF;
|
779 |
-
}
|
780 |
-
|
781 |
-
/**
|
782 |
-
* Add
|
783 |
-
*
|
784 |
-
* _sha256() adds multiple unsigned 32-bit integers. Since PHP doesn't support unsigned integers and since the
|
785 |
-
* possibility of overflow exists, care has to be taken. BigInteger could be used but this should be faster.
|
786 |
-
*
|
787 |
-
* @param int $...
|
788 |
-
* @return int
|
789 |
-
* @see self::_sha256()
|
790 |
-
* @access private
|
791 |
-
*/
|
792 |
-
function _add()
|
793 |
-
{
|
794 |
-
static $mod;
|
795 |
-
if (!isset($mod)) {
|
796 |
-
$mod = pow(2, 32);
|
797 |
-
}
|
798 |
-
|
799 |
-
$result = 0;
|
800 |
-
$arguments = func_get_args();
|
801 |
-
foreach ($arguments as $argument) {
|
802 |
-
$result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument;
|
803 |
-
}
|
804 |
-
|
805 |
-
return fmod($result, $mod);
|
806 |
-
}
|
807 |
-
|
808 |
-
/**
|
809 |
-
* String Shift
|
810 |
-
*
|
811 |
-
* Inspired by array_shift
|
812 |
-
*
|
813 |
-
* @param string $string
|
814 |
-
* @param int $index
|
815 |
-
* @return string
|
816 |
-
* @access private
|
817 |
-
*/
|
818 |
-
function _string_shift(&$string, $index = 1)
|
819 |
-
{
|
820 |
-
$substr = substr($string, 0, $index);
|
821 |
-
$string = substr($string, $index);
|
822 |
-
return $substr;
|
823 |
-
}
|
824 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/phpseclib/phpseclib/phpseclib/Crypt/RC2.php
DELETED
@@ -1,688 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Pure-PHP implementation of RC2.
|
5 |
-
*
|
6 |
-
* Uses mcrypt, if available, and an internal implementation, otherwise.
|
7 |
-
*
|
8 |
-
* PHP version 5
|
9 |
-
*
|
10 |
-
* Useful resources are as follows:
|
11 |
-
*
|
12 |
-
* - {@link http://tools.ietf.org/html/rfc2268}
|
13 |
-
*
|
14 |
-
* Here's a short example of how to use this library:
|
15 |
-
* <code>
|
16 |
-
* <?php
|
17 |
-
* include 'vendor/autoload.php';
|
18 |
-
*
|
19 |
-
* $rc2 = new \phpseclib\Crypt\RC2();
|
20 |
-
*
|
21 |
-
* $rc2->setKey('abcdefgh');
|
22 |
-
*
|
23 |
-
* $plaintext = str_repeat('a', 1024);
|
24 |
-
*
|
25 |
-
* echo $rc2->decrypt($rc2->encrypt($plaintext));
|
26 |
-
* ?>
|
27 |
-
* </code>
|
28 |
-
*
|
29 |
-
* @category Crypt
|
30 |
-
* @package RC2
|
31 |
-
* @author Patrick Monnerat <pm@datasphere.ch>
|
32 |
-
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
33 |
-
* @link http://phpseclib.sourceforge.net
|
34 |
-
*/
|
35 |
-
|
36 |
-
namespace phpseclib\Crypt;
|
37 |
-
|
38 |
-
/**
|
39 |
-
* Pure-PHP implementation of RC2.
|
40 |
-
*
|
41 |
-
* @package RC2
|
42 |
-
* @access public
|
43 |
-
*/
|
44 |
-
class RC2 extends Base
|
45 |
-
{
|
46 |
-
/**
|
47 |
-
* Block Length of the cipher
|
48 |
-
*
|
49 |
-
* @see \phpseclib\Crypt\Base::block_size
|
50 |
-
* @var int
|
51 |
-
* @access private
|
52 |
-
*/
|
53 |
-
var $block_size = 8;
|
54 |
-
|
55 |
-
/**
|
56 |
-
* The Key
|
57 |
-
*
|
58 |
-
* @see \phpseclib\Crypt\Base::key
|
59 |
-
* @see self::setKey()
|
60 |
-
* @var string
|
61 |
-
* @access private
|
62 |
-
*/
|
63 |
-
var $key;
|
64 |
-
|
65 |
-
/**
|
66 |
-
* The Original (unpadded) Key
|
67 |
-
*
|
68 |
-
* @see \phpseclib\Crypt\Base::key
|
69 |
-
* @see self::setKey()
|
70 |
-
* @see self::encrypt()
|
71 |
-
* @see self::decrypt()
|
72 |
-
* @var string
|
73 |
-
* @access private
|
74 |
-
*/
|
75 |
-
var $orig_key;
|
76 |
-
|
77 |
-
/**
|
78 |
-
* Don't truncate / null pad key
|
79 |
-
*
|
80 |
-
* @see \phpseclib\Crypt\Base::_clearBuffers()
|
81 |
-
* @var bool
|
82 |
-
* @access private
|
83 |
-
*/
|
84 |
-
var $skip_key_adjustment = true;
|
85 |
-
|
86 |
-
/**
|
87 |
-
* Key Length (in bytes)
|
88 |
-
*
|
89 |
-
* @see \phpseclib\Crypt\RC2::setKeyLength()
|
90 |
-
* @var int
|
91 |
-
* @access private
|
92 |
-
*/
|
93 |
-
var $key_length = 16; // = 128 bits
|
94 |
-
|
95 |
-
/**
|
96 |
-
* The mcrypt specific name of the cipher
|
97 |
-
*
|
98 |
-
* @see \phpseclib\Crypt\Base::cipher_name_mcrypt
|
99 |
-
* @var string
|
100 |
-
* @access private
|
101 |
-
*/
|
102 |
-
var $cipher_name_mcrypt = 'rc2';
|
103 |
-
|
104 |
-
/**
|
105 |
-
* Optimizing value while CFB-encrypting
|
106 |
-
*
|
107 |
-
* @see \phpseclib\Crypt\Base::cfb_init_len
|
108 |
-
* @var int
|
109 |
-
* @access private
|
110 |
-
*/
|
111 |
-
var $cfb_init_len = 500;
|
112 |
-
|
113 |
-
/**
|
114 |
-
* The key length in bits.
|
115 |
-
*
|
116 |
-
* @see self::setKeyLength()
|
117 |
-
* @see self::setKey()
|
118 |
-
* @var int
|
119 |
-
* @access private
|
120 |
-
* @internal Should be in range [1..1024].
|
121 |
-
* @internal Changing this value after setting the key has no effect.
|
122 |
-
*/
|
123 |
-
var $default_key_length = 1024;
|
124 |
-
|
125 |
-
/**
|
126 |
-
* The key length in bits.
|
127 |
-
*
|
128 |
-
* @see self::isValidEnine()
|
129 |
-
* @see self::setKey()
|
130 |
-
* @var int
|
131 |
-
* @access private
|
132 |
-
* @internal Should be in range [1..1024].
|
133 |
-
*/
|
134 |
-
var $current_key_length;
|
135 |
-
|
136 |
-
/**
|
137 |
-
* The Key Schedule
|
138 |
-
*
|
139 |
-
* @see self::_setupKey()
|
140 |
-
* @var array
|
141 |
-
* @access private
|
142 |
-
*/
|
143 |
-
var $keys;
|
144 |
-
|
145 |
-
/**
|
146 |
-
* Key expansion randomization table.
|
147 |
-
* Twice the same 256-value sequence to save a modulus in key expansion.
|
148 |
-
*
|
149 |
-
* @see self::setKey()
|
150 |
-
* @var array
|
151 |
-
* @access private
|
152 |
-
*/
|
153 |
-
var $pitable = array(
|
154 |
-
0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED,
|
155 |
-
0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D,
|
156 |
-
0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E,
|
157 |
-
0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2,
|
158 |
-
0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13,
|
159 |
-
0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32,
|
160 |
-
0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B,
|
161 |
-
0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82,
|
162 |
-
0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C,
|
163 |
-
0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC,
|
164 |
-
0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1,
|
165 |
-
0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26,
|
166 |
-
0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57,
|
167 |
-
0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03,
|
168 |
-
0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7,
|
169 |
-
0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7,
|
170 |
-
0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7,
|
171 |
-
0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A,
|
172 |
-
0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74,
|
173 |
-
0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC,
|
174 |
-
0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC,
|
175 |
-
0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39,
|
176 |
-
0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A,
|
177 |
-
0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31,
|
178 |
-
0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE,
|
179 |
-
0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9,
|
180 |
-
0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C,
|
181 |
-
0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9,
|
182 |
-
0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0,
|
183 |
-
0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E,
|
184 |
-
0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77,
|
185 |
-
0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD,
|
186 |
-
0xD9, 0x78, 0xF9, 0xC4, 0x19, 0xDD, 0xB5, 0xED,
|
187 |
-
0x28, 0xE9, 0xFD, 0x79, 0x4A, 0xA0, 0xD8, 0x9D,
|
188 |
-
0xC6, 0x7E, 0x37, 0x83, 0x2B, 0x76, 0x53, 0x8E,
|
189 |
-
0x62, 0x4C, 0x64, 0x88, 0x44, 0x8B, 0xFB, 0xA2,
|
190 |
-
0x17, 0x9A, 0x59, 0xF5, 0x87, 0xB3, 0x4F, 0x13,
|
191 |
-
0x61, 0x45, 0x6D, 0x8D, 0x09, 0x81, 0x7D, 0x32,
|
192 |
-
0xBD, 0x8F, 0x40, 0xEB, 0x86, 0xB7, 0x7B, 0x0B,
|
193 |
-
0xF0, 0x95, 0x21, 0x22, 0x5C, 0x6B, 0x4E, 0x82,
|
194 |
-
0x54, 0xD6, 0x65, 0x93, 0xCE, 0x60, 0xB2, 0x1C,
|
195 |
-
0x73, 0x56, 0xC0, 0x14, 0xA7, 0x8C, 0xF1, 0xDC,
|
196 |
-
0x12, 0x75, 0xCA, 0x1F, 0x3B, 0xBE, 0xE4, 0xD1,
|
197 |
-
0x42, 0x3D, 0xD4, 0x30, 0xA3, 0x3C, 0xB6, 0x26,
|
198 |
-
0x6F, 0xBF, 0x0E, 0xDA, 0x46, 0x69, 0x07, 0x57,
|
199 |
-
0x27, 0xF2, 0x1D, 0x9B, 0xBC, 0x94, 0x43, 0x03,
|
200 |
-
0xF8, 0x11, 0xC7, 0xF6, 0x90, 0xEF, 0x3E, 0xE7,
|
201 |
-
0x06, 0xC3, 0xD5, 0x2F, 0xC8, 0x66, 0x1E, 0xD7,
|
202 |
-
0x08, 0xE8, 0xEA, 0xDE, 0x80, 0x52, 0xEE, 0xF7,
|
203 |
-
0x84, 0xAA, 0x72, 0xAC, 0x35, 0x4D, 0x6A, 0x2A,
|
204 |
-
0x96, 0x1A, 0xD2, 0x71, 0x5A, 0x15, 0x49, 0x74,
|
205 |
-
0x4B, 0x9F, 0xD0, 0x5E, 0x04, 0x18, 0xA4, 0xEC,
|
206 |
-
0xC2, 0xE0, 0x41, 0x6E, 0x0F, 0x51, 0xCB, 0xCC,
|
207 |
-
0x24, 0x91, 0xAF, 0x50, 0xA1, 0xF4, 0x70, 0x39,
|
208 |
-
0x99, 0x7C, 0x3A, 0x85, 0x23, 0xB8, 0xB4, 0x7A,
|
209 |
-
0xFC, 0x02, 0x36, 0x5B, 0x25, 0x55, 0x97, 0x31,
|
210 |
-
0x2D, 0x5D, 0xFA, 0x98, 0xE3, 0x8A, 0x92, 0xAE,
|
211 |
-
0x05, 0xDF, 0x29, 0x10, 0x67, 0x6C, 0xBA, 0xC9,
|
212 |
-
0xD3, 0x00, 0xE6, 0xCF, 0xE1, 0x9E, 0xA8, 0x2C,
|
213 |
-
0x63, 0x16, 0x01, 0x3F, 0x58, 0xE2, 0x89, 0xA9,
|
214 |
-
0x0D, 0x38, 0x34, 0x1B, 0xAB, 0x33, 0xFF, 0xB0,
|
215 |
-
0xBB, 0x48, 0x0C, 0x5F, 0xB9, 0xB1, 0xCD, 0x2E,
|
216 |
-
0xC5, 0xF3, 0xDB, 0x47, 0xE5, 0xA5, 0x9C, 0x77,
|
217 |
-
0x0A, 0xA6, 0x20, 0x68, 0xFE, 0x7F, 0xC1, 0xAD
|
218 |
-
);
|
219 |
-
|
220 |
-
/**
|
221 |
-
* Inverse key expansion randomization table.
|
222 |
-
*
|
223 |
-
* @see self::setKey()
|
224 |
-
* @var array
|
225 |
-
* @access private
|
226 |
-
*/
|
227 |
-
var $invpitable = array(
|
228 |
-
0xD1, 0xDA, 0xB9, 0x6F, 0x9C, 0xC8, 0x78, 0x66,
|
229 |
-
0x80, 0x2C, 0xF8, 0x37, 0xEA, 0xE0, 0x62, 0xA4,
|
230 |
-
0xCB, 0x71, 0x50, 0x27, 0x4B, 0x95, 0xD9, 0x20,
|
231 |
-
0x9D, 0x04, 0x91, 0xE3, 0x47, 0x6A, 0x7E, 0x53,
|
232 |
-
0xFA, 0x3A, 0x3B, 0xB4, 0xA8, 0xBC, 0x5F, 0x68,
|
233 |
-
0x08, 0xCA, 0x8F, 0x14, 0xD7, 0xC0, 0xEF, 0x7B,
|
234 |
-
0x5B, 0xBF, 0x2F, 0xE5, 0xE2, 0x8C, 0xBA, 0x12,
|
235 |
-
0xE1, 0xAF, 0xB2, 0x54, 0x5D, 0x59, 0x76, 0xDB,
|
236 |
-
0x32, 0xA2, 0x58, 0x6E, 0x1C, 0x29, 0x64, 0xF3,
|
237 |
-
0xE9, 0x96, 0x0C, 0x98, 0x19, 0x8D, 0x3E, 0x26,
|
238 |
-
0xAB, 0xA5, 0x85, 0x16, 0x40, 0xBD, 0x49, 0x67,
|
239 |
-
0xDC, 0x22, 0x94, 0xBB, 0x3C, 0xC1, 0x9B, 0xEB,
|
240 |
-
0x45, 0x28, 0x18, 0xD8, 0x1A, 0x42, 0x7D, 0xCC,
|
241 |
-
0xFB, 0x65, 0x8E, 0x3D, 0xCD, 0x2A, 0xA3, 0x60,
|
242 |
-
0xAE, 0x93, 0x8A, 0x48, 0x97, 0x51, 0x15, 0xF7,
|
243 |
-
0x01, 0x0B, 0xB7, 0x36, 0xB1, 0x2E, 0x11, 0xFD,
|
244 |
-
0x84, 0x2D, 0x3F, 0x13, 0x88, 0xB3, 0x34, 0x24,
|
245 |
-
0x1B, 0xDE, 0xC5, 0x1D, 0x4D, 0x2B, 0x17, 0x31,
|
246 |
-
0x74, 0xA9, 0xC6, 0x43, 0x6D, 0x39, 0x90, 0xBE,
|
247 |
-
0xC3, 0xB0, 0x21, 0x6B, 0xF6, 0x0F, 0xD5, 0x99,
|
248 |
-
0x0D, 0xAC, 0x1F, 0x5C, 0x9E, 0xF5, 0xF9, 0x4C,
|
249 |
-
0xD6, 0xDF, 0x89, 0xE4, 0x8B, 0xFF, 0xC7, 0xAA,
|
250 |
-
0xE7, 0xED, 0x46, 0x25, 0xB6, 0x06, 0x5E, 0x35,
|
251 |
-
0xB5, 0xEC, 0xCE, 0xE8, 0x6C, 0x30, 0x55, 0x61,
|
252 |
-
0x4A, 0xFE, 0xA0, 0x79, 0x03, 0xF0, 0x10, 0x72,
|
253 |
-
0x7C, 0xCF, 0x52, 0xA6, 0xA7, 0xEE, 0x44, 0xD3,
|
254 |
-
0x9A, 0x57, 0x92, 0xD0, 0x5A, 0x7A, 0x41, 0x7F,
|
255 |
-
0x0E, 0x00, 0x63, 0xF2, 0x4F, 0x05, 0x83, 0xC9,
|
256 |
-
0xA1, 0xD4, 0xDD, 0xC4, 0x56, 0xF4, 0xD2, 0x77,
|
257 |
-
0x81, 0x09, 0x82, 0x33, 0x9F, 0x07, 0x86, 0x75,
|
258 |
-
0x38, 0x4E, 0x69, 0xF1, 0xAD, 0x23, 0x73, 0x87,
|
259 |
-
0x70, 0x02, 0xC2, 0x1E, 0xB8, 0x0A, 0xFC, 0xE6
|
260 |
-
);
|
261 |
-
|
262 |
-
/**
|
263 |
-
* Test for engine validity
|
264 |
-
*
|
265 |
-
* This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
|
266 |
-
*
|
267 |
-
* @see \phpseclib\Crypt\Base::__construct()
|
268 |
-
* @param int $engine
|
269 |
-
* @access public
|
270 |
-
* @return bool
|
271 |
-
*/
|
272 |
-
function isValidEngine($engine)
|
273 |
-
{
|
274 |
-
switch ($engine) {
|
275 |
-
case self::ENGINE_OPENSSL:
|
276 |
-
if ($this->current_key_length != 128 || strlen($this->orig_key) < 16) {
|
277 |
-
return false;
|
278 |
-
}
|
279 |
-
$this->cipher_name_openssl_ecb = 'rc2-ecb';
|
280 |
-
$this->cipher_name_openssl = 'rc2-' . $this->_openssl_translate_mode();
|
281 |
-
}
|
282 |
-
|
283 |
-
return parent::isValidEngine($engine);
|
284 |
-
}
|
285 |
-
|
286 |
-
/**
|
287 |
-
* Sets the key length.
|
288 |
-
*
|
289 |
-
* Valid key lengths are 8 to 1024.
|
290 |
-
* Calling this function after setting the key has no effect until the next
|
291 |
-
* \phpseclib\Crypt\RC2::setKey() call.
|
292 |
-
*
|
293 |
-
* @access public
|
294 |
-
* @param int $length in bits
|
295 |
-
*/
|
296 |
-
function setKeyLength($length)
|
297 |
-
{
|
298 |
-
if ($length < 8) {
|
299 |
-
$this->default_key_length = 8;
|
300 |
-
} elseif ($length > 1024) {
|
301 |
-
$this->default_key_length = 128;
|
302 |
-
} else {
|
303 |
-
$this->default_key_length = $length;
|
304 |
-
}
|
305 |
-
$this->current_key_length = $this->default_key_length;
|
306 |
-
|
307 |
-
parent::setKeyLength($length);
|
308 |
-
}
|
309 |
-
|
310 |
-
/**
|
311 |
-
* Returns the current key length
|
312 |
-
*
|
313 |
-
* @access public
|
314 |
-
* @return int
|
315 |
-
*/
|
316 |
-
function getKeyLength()
|
317 |
-
{
|
318 |
-
return $this->current_key_length;
|
319 |
-
}
|
320 |
-
|
321 |
-
/**
|
322 |
-
* Sets the key.
|
323 |
-
*
|
324 |
-
* Keys can be of any length. RC2, itself, uses 8 to 1024 bit keys (eg.
|
325 |
-
* strlen($key) <= 128), however, we only use the first 128 bytes if $key
|
326 |
-
* has more then 128 bytes in it, and set $key to a single null byte if
|
327 |
-
* it is empty.
|
328 |
-
*
|
329 |
-
* If the key is not explicitly set, it'll be assumed to be a single
|
330 |
-
* null byte.
|
331 |
-
*
|
332 |
-
* @see \phpseclib\Crypt\Base::setKey()
|
333 |
-
* @access public
|
334 |
-
* @param string $key
|
335 |
-
* @param int $t1 optional Effective key length in bits.
|
336 |
-
*/
|
337 |
-
function setKey($key, $t1 = 0)
|
338 |
-
{
|
339 |
-
$this->orig_key = $key;
|
340 |
-
|
341 |
-
if ($t1 <= 0) {
|
342 |
-
$t1 = $this->default_key_length;
|
343 |
-
} elseif ($t1 > 1024) {
|
344 |
-
$t1 = 1024;
|
345 |
-
}
|
346 |
-
$this->current_key_length = $t1;
|
347 |
-
// Key byte count should be 1..128.
|
348 |
-
$key = strlen($key) ? substr($key, 0, 128) : "\x00";
|
349 |
-
$t = strlen($key);
|
350 |
-
|
351 |
-
// The mcrypt RC2 implementation only supports effective key length
|
352 |
-
// of 1024 bits. It is however possible to handle effective key
|
353 |
-
// lengths in range 1..1024 by expanding the key and applying
|
354 |
-
// inverse pitable mapping to the first byte before submitting it
|
355 |
-
// to mcrypt.
|
356 |
-
|
357 |
-
// Key expansion.
|
358 |
-
$l = array_values(unpack('C*', $key));
|
359 |
-
$t8 = ($t1 + 7) >> 3;
|
360 |
-
$tm = 0xFF >> (8 * $t8 - $t1);
|
361 |
-
|
362 |
-
// Expand key.
|
363 |
-
$pitable = $this->pitable;
|
364 |
-
for ($i = $t; $i < 128; $i++) {
|
365 |
-
$l[$i] = $pitable[$l[$i - 1] + $l[$i - $t]];
|
366 |
-
}
|
367 |
-
$i = 128 - $t8;
|
368 |
-
$l[$i] = $pitable[$l[$i] & $tm];
|
369 |
-
while ($i--) {
|
370 |
-
$l[$i] = $pitable[$l[$i + 1] ^ $l[$i + $t8]];
|
371 |
-
}
|
372 |
-
|
373 |
-
// Prepare the key for mcrypt.
|
374 |
-
$l[0] = $this->invpitable[$l[0]];
|
375 |
-
array_unshift($l, 'C*');
|
376 |
-
|
377 |
-
parent::setKey(call_user_func_array('pack', $l));
|
378 |
-
}
|
379 |
-
|
380 |
-
/**
|
381 |
-
* Encrypts a message.
|
382 |
-
*
|
383 |
-
* Mostly a wrapper for \phpseclib\Crypt\Base::encrypt, with some additional OpenSSL handling code
|
384 |
-
*
|
385 |
-
* @see self::decrypt()
|
386 |
-
* @access public
|
387 |
-
* @param string $plaintext
|
388 |
-
* @return string $ciphertext
|
389 |
-
*/
|
390 |
-
function encrypt($plaintext)
|
391 |
-
{
|
392 |
-
if ($this->engine == self::ENGINE_OPENSSL) {
|
393 |
-
$temp = $this->key;
|
394 |
-
$this->key = $this->orig_key;
|
395 |
-
$result = parent::encrypt($plaintext);
|
396 |
-
$this->key = $temp;
|
397 |
-
return $result;
|
398 |
-
}
|
399 |
-
|
400 |
-
return parent::encrypt($plaintext);
|
401 |
-
}
|
402 |
-
|
403 |
-
/**
|
404 |
-
* Decrypts a message.
|
405 |
-
*
|
406 |
-
* Mostly a wrapper for \phpseclib\Crypt\Base::decrypt, with some additional OpenSSL handling code
|
407 |
-
*
|
408 |
-
* @see self::encrypt()
|
409 |
-
* @access public
|
410 |
-
* @param string $ciphertext
|
411 |
-
* @return string $plaintext
|
412 |
-
*/
|
413 |
-
function decrypt($ciphertext)
|
414 |
-
{
|
415 |
-
if ($this->engine == self::ENGINE_OPENSSL) {
|
416 |
-
$temp = $this->key;
|
417 |
-
$this->key = $this->orig_key;
|
418 |
-
$result = parent::decrypt($ciphertext);
|
419 |
-
$this->key = $temp;
|
420 |
-
return $result;
|
421 |
-
}
|
422 |
-
|
423 |
-
return parent::decrypt($ciphertext);
|
424 |
-
}
|
425 |
-
|
426 |
-
/**
|
427 |
-
* Encrypts a block
|
428 |
-
*
|
429 |
-
* @see \phpseclib\Crypt\Base::_encryptBlock()
|
430 |
-
* @see \phpseclib\Crypt\Base::encrypt()
|
431 |
-
* @access private
|
432 |
-
* @param string $in
|
433 |
-
* @return string
|
434 |
-
*/
|
435 |
-
function _encryptBlock($in)
|
436 |
-
{
|
437 |
-
list($r0, $r1, $r2, $r3) = array_values(unpack('v*', $in));
|
438 |
-
$keys = $this->keys;
|
439 |
-
$limit = 20;
|
440 |
-
$actions = array($limit => 44, 44 => 64);
|
441 |
-
$j = 0;
|
442 |
-
|
443 |
-
for (;;) {
|
444 |
-
// Mixing round.
|
445 |
-
$r0 = (($r0 + $keys[$j++] + ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF) << 1;
|
446 |
-
$r0 |= $r0 >> 16;
|
447 |
-
$r1 = (($r1 + $keys[$j++] + ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF) << 2;
|
448 |
-
$r1 |= $r1 >> 16;
|
449 |
-
$r2 = (($r2 + $keys[$j++] + ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF) << 3;
|
450 |
-
$r2 |= $r2 >> 16;
|
451 |
-
$r3 = (($r3 + $keys[$j++] + ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5;
|
452 |
-
$r3 |= $r3 >> 16;
|
453 |
-
|
454 |
-
if ($j === $limit) {
|
455 |
-
if ($limit === 64) {
|
456 |
-
break;
|
457 |
-
}
|
458 |
-
|
459 |
-
// Mashing round.
|
460 |
-
$r0 += $keys[$r3 & 0x3F];
|
461 |
-
$r1 += $keys[$r0 & 0x3F];
|
462 |
-
$r2 += $keys[$r1 & 0x3F];
|
463 |
-
$r3 += $keys[$r2 & 0x3F];
|
464 |
-
$limit = $actions[$limit];
|
465 |
-
}
|
466 |
-
}
|
467 |
-
|
468 |
-
return pack('vvvv', $r0, $r1, $r2, $r3);
|
469 |
-
}
|
470 |
-
|
471 |
-
/**
|
472 |
-
* Decrypts a block
|
473 |
-
*
|
474 |
-
* @see \phpseclib\Crypt\Base::_decryptBlock()
|
475 |
-
* @see \phpseclib\Crypt\Base::decrypt()
|
476 |
-
* @access private
|
477 |
-
* @param string $in
|
478 |
-
* @return string
|
479 |
-
*/
|
480 |
-
function _decryptBlock($in)
|
481 |
-
{
|
482 |
-
list($r0, $r1, $r2, $r3) = array_values(unpack('v*', $in));
|
483 |
-
$keys = $this->keys;
|
484 |
-
$limit = 44;
|
485 |
-
$actions = array($limit => 20, 20 => 0);
|
486 |
-
$j = 64;
|
487 |
-
|
488 |
-
for (;;) {
|
489 |
-
// R-mixing round.
|
490 |
-
$r3 = ($r3 | ($r3 << 16)) >> 5;
|
491 |
-
$r3 = ($r3 - $keys[--$j] - ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF;
|
492 |
-
$r2 = ($r2 | ($r2 << 16)) >> 3;
|
493 |
-
$r2 = ($r2 - $keys[--$j] - ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF;
|
494 |
-
$r1 = ($r1 | ($r1 << 16)) >> 2;
|
495 |
-
$r1 = ($r1 - $keys[--$j] - ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF;
|
496 |
-
$r0 = ($r0 | ($r0 << 16)) >> 1;
|
497 |
-
$r0 = ($r0 - $keys[--$j] - ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF;
|
498 |
-
|
499 |
-
if ($j === $limit) {
|
500 |
-
if ($limit === 0) {
|
501 |
-
break;
|
502 |
-
}
|
503 |
-
|
504 |
-
// R-mashing round.
|
505 |
-
$r3 = ($r3 - $keys[$r2 & 0x3F]) & 0xFFFF;
|
506 |
-
$r2 = ($r2 - $keys[$r1 & 0x3F]) & 0xFFFF;
|
507 |
-
$r1 = ($r1 - $keys[$r0 & 0x3F]) & 0xFFFF;
|
508 |
-
$r0 = ($r0 - $keys[$r3 & 0x3F]) & 0xFFFF;
|
509 |
-
$limit = $actions[$limit];
|
510 |
-
}
|
511 |
-
}
|
512 |
-
|
513 |
-
return pack('vvvv', $r0, $r1, $r2, $r3);
|
514 |
-
}
|
515 |
-
|
516 |
-
/**
|
517 |
-
* Setup the \phpseclib\Crypt\Base::ENGINE_MCRYPT $engine
|
518 |
-
*
|
519 |
-
* @see \phpseclib\Crypt\Base::_setupMcrypt()
|
520 |
-
* @access private
|
521 |
-
*/
|
522 |
-
function _setupMcrypt()
|
523 |
-
{
|
524 |
-
if (!isset($this->key)) {
|
525 |
-
$this->setKey('');
|
526 |
-
}
|
527 |
-
|
528 |
-
parent::_setupMcrypt();
|
529 |
-
}
|
530 |
-
|
531 |
-
/**
|
532 |
-
* Creates the key schedule
|
533 |
-
*
|
534 |
-
* @see \phpseclib\Crypt\Base::_setupKey()
|
535 |
-
* @access private
|
536 |
-
*/
|
537 |
-
function _setupKey()
|
538 |
-
{
|
539 |
-
if (!isset($this->key)) {
|
540 |
-
$this->setKey('');
|
541 |
-
}
|
542 |
-
|
543 |
-
// Key has already been expanded in \phpseclib\Crypt\RC2::setKey():
|
544 |
-
// Only the first value must be altered.
|
545 |
-
$l = unpack('Ca/Cb/v*', $this->key);
|
546 |
-
array_unshift($l, $this->pitable[$l['a']] | ($l['b'] << 8));
|
547 |
-
unset($l['a']);
|
548 |
-
unset($l['b']);
|
549 |
-
$this->keys = $l;
|
550 |
-
}
|
551 |
-
|
552 |
-
/**
|
553 |
-
* Setup the performance-optimized function for de/encrypt()
|
554 |
-
*
|
555 |
-
* @see \phpseclib\Crypt\Base::_setupInlineCrypt()
|
556 |
-
* @access private
|
557 |
-
*/
|
558 |
-
function _setupInlineCrypt()
|
559 |
-
{
|
560 |
-
$lambda_functions =& self::_getLambdaFunctions();
|
561 |
-
|
562 |
-
// The first 10 generated $lambda_functions will use the $keys hardcoded as integers
|
563 |
-
// for the mixing rounds, for better inline crypt performance [~20% faster].
|
564 |
-
// But for memory reason we have to limit those ultra-optimized $lambda_functions to an amount of 10.
|
565 |
-
// (Currently, for Crypt_RC2, one generated $lambda_function cost on php5.5@32bit ~60kb unfreeable mem and ~100kb on php5.5@64bit)
|
566 |
-
$gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
|
567 |
-
|
568 |
-
// Generation of a unique hash for our generated code
|
569 |
-
$code_hash = "Crypt_RC2, {$this->mode}";
|
570 |
-
if ($gen_hi_opt_code) {
|
571 |
-
$code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
|
572 |
-
}
|
573 |
-
|
574 |
-
// Is there a re-usable $lambda_functions in there?
|
575 |
-
// If not, we have to create it.
|
576 |
-
if (!isset($lambda_functions[$code_hash])) {
|
577 |
-
// Init code for both, encrypt and decrypt.
|
578 |
-
$init_crypt = '$keys = $self->keys;';
|
579 |
-
|
580 |
-
switch (true) {
|
581 |
-
case $gen_hi_opt_code:
|
582 |
-
$keys = $this->keys;
|
583 |
-
default:
|
584 |
-
$keys = array();
|
585 |
-
foreach ($this->keys as $k => $v) {
|
586 |
-
$keys[$k] = '$keys[' . $k . ']';
|
587 |
-
}
|
588 |
-
}
|
589 |
-
|
590 |
-
// $in is the current 8 bytes block which has to be en/decrypt
|
591 |
-
$encrypt_block = $decrypt_block = '
|
592 |
-
$in = unpack("v4", $in);
|
593 |
-
$r0 = $in[1];
|
594 |
-
$r1 = $in[2];
|
595 |
-
$r2 = $in[3];
|
596 |
-
$r3 = $in[4];
|
597 |
-
';
|
598 |
-
|
599 |
-
// Create code for encryption.
|
600 |
-
$limit = 20;
|
601 |
-
$actions = array($limit => 44, 44 => 64);
|
602 |
-
$j = 0;
|
603 |
-
|
604 |
-
for (;;) {
|
605 |
-
// Mixing round.
|
606 |
-
$encrypt_block .= '
|
607 |
-
$r0 = (($r0 + ' . $keys[$j++] . ' +
|
608 |
-
((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF) << 1;
|
609 |
-
$r0 |= $r0 >> 16;
|
610 |
-
$r1 = (($r1 + ' . $keys[$j++] . ' +
|
611 |
-
((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF) << 2;
|
612 |
-
$r1 |= $r1 >> 16;
|
613 |
-
$r2 = (($r2 + ' . $keys[$j++] . ' +
|
614 |
-
((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF) << 3;
|
615 |
-
$r2 |= $r2 >> 16;
|
616 |
-
$r3 = (($r3 + ' . $keys[$j++] . ' +
|
617 |
-
((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5;
|
618 |
-
$r3 |= $r3 >> 16;';
|
619 |
-
|
620 |
-
if ($j === $limit) {
|
621 |
-
if ($limit === 64) {
|
622 |
-
break;
|
623 |
-
}
|
624 |
-
|
625 |
-
// Mashing round.
|
626 |
-
$encrypt_block .= '
|
627 |
-
$r0 += $keys[$r3 & 0x3F];
|
628 |
-
$r1 += $keys[$r0 & 0x3F];
|
629 |
-
$r2 += $keys[$r1 & 0x3F];
|
630 |
-
$r3 += $keys[$r2 & 0x3F];';
|
631 |
-
$limit = $actions[$limit];
|
632 |
-
}
|
633 |
-
}
|
634 |
-
|
635 |
-
$encrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);';
|
636 |
-
|
637 |
-
// Create code for decryption.
|
638 |
-
$limit = 44;
|
639 |
-
$actions = array($limit => 20, 20 => 0);
|
640 |
-
$j = 64;
|
641 |
-
|
642 |
-
for (;;) {
|
643 |
-
// R-mixing round.
|
644 |
-
$decrypt_block .= '
|
645 |
-
$r3 = ($r3 | ($r3 << 16)) >> 5;
|
646 |
-
$r3 = ($r3 - ' . $keys[--$j] . ' -
|
647 |
-
((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF;
|
648 |
-
$r2 = ($r2 | ($r2 << 16)) >> 3;
|
649 |
-
$r2 = ($r2 - ' . $keys[--$j] . ' -
|
650 |
-
((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF;
|
651 |
-
$r1 = ($r1 | ($r1 << 16)) >> 2;
|
652 |
-
$r1 = ($r1 - ' . $keys[--$j] . ' -
|
653 |
-
((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF;
|
654 |
-
$r0 = ($r0 | ($r0 << 16)) >> 1;
|
655 |
-
$r0 = ($r0 - ' . $keys[--$j] . ' -
|
656 |
-
((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF;';
|
657 |
-
|
658 |
-
if ($j === $limit) {
|
659 |
-
if ($limit === 0) {
|
660 |
-
break;
|
661 |
-
}
|
662 |
-
|
663 |
-
// R-mashing round.
|
664 |
-
$decrypt_block .= '
|
665 |
-
$r3 = ($r3 - $keys[$r2 & 0x3F]) & 0xFFFF;
|
666 |
-
$r2 = ($r2 - $keys[$r1 & 0x3F]) & 0xFFFF;
|
667 |
-
$r1 = ($r1 - $keys[$r0 & 0x3F]) & 0xFFFF;
|
668 |
-
$r0 = ($r0 - $keys[$r3 & 0x3F]) & 0xFFFF;';
|
669 |
-
$limit = $actions[$limit];
|
670 |
-
}
|
671 |
-
}
|
672 |
-
|
673 |
-
$decrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);';
|
674 |
-
|
675 |
-
// Creates the inline-crypt function
|
676 |
-
$lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
|
677 |
-
array(
|
678 |
-
'init_crypt' => $init_crypt,
|
679 |
-
'encrypt_block' => $encrypt_block,
|
680 |
-
'decrypt_block' => $decrypt_block
|
681 |
-
)
|
682 |
-
);
|
683 |
-
}
|
684 |
-
|
685 |
-
// Set the inline-crypt function as callback in: $this->inline_crypt
|
686 |
-
$this->inline_crypt = $lambda_functions[$code_hash];
|
687 |
-
}
|
688 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/phpseclib/phpseclib/phpseclib/Crypt/RC4.php
DELETED
@@ -1,342 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Pure-PHP implementation of RC4.
|
5 |
-
*
|
6 |
-
* Uses mcrypt, if available, and an internal implementation, otherwise.
|
7 |
-
*
|
8 |
-
* PHP version 5
|
9 |
-
*
|
10 |
-
* Useful resources are as follows:
|
11 |
-
*
|
12 |
-
* - {@link http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt ARCFOUR Algorithm}
|
13 |
-
* - {@link http://en.wikipedia.org/wiki/RC4 - Wikipedia: RC4}
|
14 |
-
*
|
15 |
-
* RC4 is also known as ARCFOUR or ARC4. The reason is elaborated upon at Wikipedia. This class is named RC4 and not
|
16 |
-
* ARCFOUR or ARC4 because RC4 is how it is referred to in the SSH1 specification.
|
17 |
-
*
|
18 |
-
* Here's a short example of how to use this library:
|
19 |
-
* <code>
|
20 |
-
* <?php
|
21 |
-
* include 'vendor/autoload.php';
|
22 |
-
*
|
23 |
-
* $rc4 = new \phpseclib\Crypt\RC4();
|
24 |
-
*
|
25 |
-
* $rc4->setKey('abcdefgh');
|
26 |
-
*
|
27 |
-
* $size = 10 * 1024;
|
28 |
-
* $plaintext = '';
|
29 |
-
* for ($i = 0; $i < $size; $i++) {
|
30 |
-
* $plaintext.= 'a';
|
31 |
-
* }
|
32 |
-
*
|
33 |
-
* echo $rc4->decrypt($rc4->encrypt($plaintext));
|
34 |
-
* ?>
|
35 |
-
* </code>
|
36 |
-
*
|
37 |
-
* @category Crypt
|
38 |
-
* @package RC4
|
39 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
40 |
-
* @copyright 2007 Jim Wigginton
|
41 |
-
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
42 |
-
* @link http://phpseclib.sourceforge.net
|
43 |
-
*/
|
44 |
-
|
45 |
-
namespace phpseclib\Crypt;
|
46 |
-
|
47 |
-
/**
|
48 |
-
* Pure-PHP implementation of RC4.
|
49 |
-
*
|
50 |
-
* @package RC4
|
51 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
52 |
-
* @access public
|
53 |
-
*/
|
54 |
-
class RC4 extends Base
|
55 |
-
{
|
56 |
-
/**#@+
|
57 |
-
* @access private
|
58 |
-
* @see \phpseclib\Crypt\RC4::_crypt()
|
59 |
-
*/
|
60 |
-
const ENCRYPT = 0;
|
61 |
-
const DECRYPT = 1;
|
62 |
-
/**#@-*/
|
63 |
-
|
64 |
-
/**
|
65 |
-
* Block Length of the cipher
|
66 |
-
*
|
67 |
-
* RC4 is a stream cipher
|
68 |
-
* so we the block_size to 0
|
69 |
-
*
|
70 |
-
* @see \phpseclib\Crypt\Base::block_size
|
71 |
-
* @var int
|
72 |
-
* @access private
|
73 |
-
*/
|
74 |
-
var $block_size = 0;
|
75 |
-
|
76 |
-
/**
|
77 |
-
* Key Length (in bytes)
|
78 |
-
*
|
79 |
-
* @see \phpseclib\Crypt\RC4::setKeyLength()
|
80 |
-
* @var int
|
81 |
-
* @access private
|
82 |
-
*/
|
83 |
-
var $key_length = 128; // = 1024 bits
|
84 |
-
|
85 |
-
/**
|
86 |
-
* The mcrypt specific name of the cipher
|
87 |
-
*
|
88 |
-
* @see \phpseclib\Crypt\Base::cipher_name_mcrypt
|
89 |
-
* @var string
|
90 |
-
* @access private
|
91 |
-
*/
|
92 |
-
var $cipher_name_mcrypt = 'arcfour';
|
93 |
-
|
94 |
-
/**
|
95 |
-
* Holds whether performance-optimized $inline_crypt() can/should be used.
|
96 |
-
*
|
97 |
-
* @see \phpseclib\Crypt\Base::inline_crypt
|
98 |
-
* @var mixed
|
99 |
-
* @access private
|
100 |
-
*/
|
101 |
-
var $use_inline_crypt = false; // currently not available
|
102 |
-
|
103 |
-
/**
|
104 |
-
* The Key
|
105 |
-
*
|
106 |
-
* @see self::setKey()
|
107 |
-
* @var string
|
108 |
-
* @access private
|
109 |
-
*/
|
110 |
-
var $key;
|
111 |
-
|
112 |
-
/**
|
113 |
-
* The Key Stream for decryption and encryption
|
114 |
-
*
|
115 |
-
* @see self::setKey()
|
116 |
-
* @var array
|
117 |
-
* @access private
|
118 |
-
*/
|
119 |
-
var $stream;
|
120 |
-
|
121 |
-
/**
|
122 |
-
* Default Constructor.
|
123 |
-
*
|
124 |
-
* Determines whether or not the mcrypt extension should be used.
|
125 |
-
*
|
126 |
-
* @see \phpseclib\Crypt\Base::__construct()
|
127 |
-
* @return \phpseclib\Crypt\RC4
|
128 |
-
* @access public
|
129 |
-
*/
|
130 |
-
function __construct()
|
131 |
-
{
|
132 |
-
parent::__construct(Base::MODE_STREAM);
|
133 |
-
}
|
134 |
-
|
135 |
-
/**
|
136 |
-
* Test for engine validity
|
137 |
-
*
|
138 |
-
* This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
|
139 |
-
*
|
140 |
-
* @see \phpseclib\Crypt\Base::__construct()
|
141 |
-
* @param int $engine
|
142 |
-
* @access public
|
143 |
-
* @return bool
|
144 |
-
*/
|
145 |
-
function isValidEngine($engine)
|
146 |
-
{
|
147 |
-
if ($engine == Base::ENGINE_OPENSSL) {
|
148 |
-
if (version_compare(PHP_VERSION, '5.3.7') >= 0) {
|
149 |
-
$this->cipher_name_openssl = 'rc4-40';
|
150 |
-
} else {
|
151 |
-
switch (strlen($this->key)) {
|
152 |
-
case 5:
|
153 |
-
$this->cipher_name_openssl = 'rc4-40';
|
154 |
-
break;
|
155 |
-
case 8:
|
156 |
-
$this->cipher_name_openssl = 'rc4-64';
|
157 |
-
break;
|
158 |
-
case 16:
|
159 |
-
$this->cipher_name_openssl = 'rc4';
|
160 |
-
break;
|
161 |
-
default:
|
162 |
-
return false;
|
163 |
-
}
|
164 |
-
}
|
165 |
-
}
|
166 |
-
|
167 |
-
return parent::isValidEngine($engine);
|
168 |
-
}
|
169 |
-
|
170 |
-
/**
|
171 |
-
* Dummy function.
|
172 |
-
*
|
173 |
-
* Some protocols, such as WEP, prepend an "initialization vector" to the key, effectively creating a new key [1].
|
174 |
-
* If you need to use an initialization vector in this manner, feel free to prepend it to the key, yourself, before
|
175 |
-
* calling setKey().
|
176 |
-
*
|
177 |
-
* [1] WEP's initialization vectors (IV's) are used in a somewhat insecure way. Since, in that protocol,
|
178 |
-
* the IV's are relatively easy to predict, an attack described by
|
179 |
-
* {@link http://www.drizzle.com/~aboba/IEEE/rc4_ksaproc.pdf Scott Fluhrer, Itsik Mantin, and Adi Shamir}
|
180 |
-
* can be used to quickly guess at the rest of the key. The following links elaborate:
|
181 |
-
*
|
182 |
-
* {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009}
|
183 |
-
* {@link http://en.wikipedia.org/wiki/Related_key_attack http://en.wikipedia.org/wiki/Related_key_attack}
|
184 |
-
*
|
185 |
-
* @param string $iv
|
186 |
-
* @see self::setKey()
|
187 |
-
* @access public
|
188 |
-
*/
|
189 |
-
function setIV($iv)
|
190 |
-
{
|
191 |
-
}
|
192 |
-
|
193 |
-
/**
|
194 |
-
* Sets the key length
|
195 |
-
*
|
196 |
-
* Keys can be between 1 and 256 bytes long.
|
197 |
-
*
|
198 |
-
* @access public
|
199 |
-
* @param int $length
|
200 |
-
*/
|
201 |
-
function setKeyLength($length)
|
202 |
-
{
|
203 |
-
if ($length < 8) {
|
204 |
-
$this->key_length = 1;
|
205 |
-
} elseif ($length > 2048) {
|
206 |
-
$this->key_length = 256;
|
207 |
-
} else {
|
208 |
-
$this->key_length = $length >> 3;
|
209 |
-
}
|
210 |
-
|
211 |
-
parent::setKeyLength($length);
|
212 |
-
}
|
213 |
-
|
214 |
-
/**
|
215 |
-
* Encrypts a message.
|
216 |
-
*
|
217 |
-
* @see \phpseclib\Crypt\Base::decrypt()
|
218 |
-
* @see self::_crypt()
|
219 |
-
* @access public
|
220 |
-
* @param string $plaintext
|
221 |
-
* @return string $ciphertext
|
222 |
-
*/
|
223 |
-
function encrypt($plaintext)
|
224 |
-
{
|
225 |
-
if ($this->engine != Base::ENGINE_INTERNAL) {
|
226 |
-
return parent::encrypt($plaintext);
|
227 |
-
}
|
228 |
-
return $this->_crypt($plaintext, self::ENCRYPT);
|
229 |
-
}
|
230 |
-
|
231 |
-
/**
|
232 |
-
* Decrypts a message.
|
233 |
-
*
|
234 |
-
* $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
|
235 |
-
* At least if the continuous buffer is disabled.
|
236 |
-
*
|
237 |
-
* @see \phpseclib\Crypt\Base::encrypt()
|
238 |
-
* @see self::_crypt()
|
239 |
-
* @access public
|
240 |
-
* @param string $ciphertext
|
241 |
-
* @return string $plaintext
|
242 |
-
*/
|
243 |
-
function decrypt($ciphertext)
|
244 |
-
{
|
245 |
-
if ($this->engine != Base::ENGINE_INTERNAL) {
|
246 |
-
return parent::decrypt($ciphertext);
|
247 |
-
}
|
248 |
-
return $this->_crypt($ciphertext, self::DECRYPT);
|
249 |
-
}
|
250 |
-
|
251 |
-
/**
|
252 |
-
* Encrypts a block
|
253 |
-
*
|
254 |
-
* @access private
|
255 |
-
* @param string $in
|
256 |
-
*/
|
257 |
-
function _encryptBlock($in)
|
258 |
-
{
|
259 |
-
// RC4 does not utilize this method
|
260 |
-
}
|
261 |
-
|
262 |
-
/**
|
263 |
-
* Decrypts a block
|
264 |
-
*
|
265 |
-
* @access private
|
266 |
-
* @param string $in
|
267 |
-
*/
|
268 |
-
function _decryptBlock($in)
|
269 |
-
{
|
270 |
-
// RC4 does not utilize this method
|
271 |
-
}
|
272 |
-
|
273 |
-
/**
|
274 |
-
* Setup the key (expansion)
|
275 |
-
*
|
276 |
-
* @see \phpseclib\Crypt\Base::_setupKey()
|
277 |
-
* @access private
|
278 |
-
*/
|
279 |
-
function _setupKey()
|
280 |
-
{
|
281 |
-
$key = $this->key;
|
282 |
-
$keyLength = strlen($key);
|
283 |
-
$keyStream = range(0, 255);
|
284 |
-
$j = 0;
|
285 |
-
for ($i = 0; $i < 256; $i++) {
|
286 |
-
$j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255;
|
287 |
-
$temp = $keyStream[$i];
|
288 |
-
$keyStream[$i] = $keyStream[$j];
|
289 |
-
$keyStream[$j] = $temp;
|
290 |
-
}
|
291 |
-
|
292 |
-
$this->stream = array();
|
293 |
-
$this->stream[self::DECRYPT] = $this->stream[self::ENCRYPT] = array(
|
294 |
-
0, // index $i
|
295 |
-
0, // index $j
|
296 |
-
$keyStream
|
297 |
-
);
|
298 |
-
}
|
299 |
-
|
300 |
-
/**
|
301 |
-
* Encrypts or decrypts a message.
|
302 |
-
*
|
303 |
-
* @see self::encrypt()
|
304 |
-
* @see self::decrypt()
|
305 |
-
* @access private
|
306 |
-
* @param string $text
|
307 |
-
* @param int $mode
|
308 |
-
* @return string $text
|
309 |
-
*/
|
310 |
-
function _crypt($text, $mode)
|
311 |
-
{
|
312 |
-
if ($this->changed) {
|
313 |
-
$this->_setup();
|
314 |
-
$this->changed = false;
|
315 |
-
}
|
316 |
-
|
317 |
-
$stream = &$this->stream[$mode];
|
318 |
-
if ($this->continuousBuffer) {
|
319 |
-
$i = &$stream[0];
|
320 |
-
$j = &$stream[1];
|
321 |
-
$keyStream = &$stream[2];
|
322 |
-
} else {
|
323 |
-
$i = $stream[0];
|
324 |
-
$j = $stream[1];
|
325 |
-
$keyStream = $stream[2];
|
326 |
-
}
|
327 |
-
|
328 |
-
$len = strlen($text);
|
329 |
-
for ($k = 0; $k < $len; ++$k) {
|
330 |
-
$i = ($i + 1) & 255;
|
331 |
-
$ksi = $keyStream[$i];
|
332 |
-
$j = ($j + $ksi) & 255;
|
333 |
-
$ksj = $keyStream[$j];
|
334 |
-
|
335 |
-
$keyStream[$i] = $ksj;
|
336 |
-
$keyStream[$j] = $ksi;
|
337 |
-
$text[$k] = $text[$k] ^ chr($keyStream[($ksj + $ksi) & 255]);
|
338 |
-
}
|
339 |
-
|
340 |
-
return $text;
|
341 |
-
}
|
342 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php
DELETED
@@ -1,460 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Pure-PHP implementation of Triple DES.
|
5 |
-
*
|
6 |
-
* Uses mcrypt, if available, and an internal implementation, otherwise. Operates in the EDE3 mode (encrypt-decrypt-encrypt).
|
7 |
-
*
|
8 |
-
* PHP version 5
|
9 |
-
*
|
10 |
-
* Here's a short example of how to use this library:
|
11 |
-
* <code>
|
12 |
-
* <?php
|
13 |
-
* include 'vendor/autoload.php';
|
14 |
-
*
|
15 |
-
* $des = new \phpseclib\Crypt\TripleDES();
|
16 |
-
*
|
17 |
-
* $des->setKey('abcdefghijklmnopqrstuvwx');
|
18 |
-
*
|
19 |
-
* $size = 10 * 1024;
|
20 |
-
* $plaintext = '';
|
21 |
-
* for ($i = 0; $i < $size; $i++) {
|
22 |
-
* $plaintext.= 'a';
|
23 |
-
* }
|
24 |
-
*
|
25 |
-
* echo $des->decrypt($des->encrypt($plaintext));
|
26 |
-
* ?>
|
27 |
-
* </code>
|
28 |
-
*
|
29 |
-
* @category Crypt
|
30 |
-
* @package TripleDES
|
31 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
32 |
-
* @copyright 2007 Jim Wigginton
|
33 |
-
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
34 |
-
* @link http://phpseclib.sourceforge.net
|
35 |
-
*/
|
36 |
-
|
37 |
-
namespace phpseclib\Crypt;
|
38 |
-
|
39 |
-
/**
|
40 |
-
* Pure-PHP implementation of Triple DES.
|
41 |
-
*
|
42 |
-
* @package TripleDES
|
43 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
44 |
-
* @access public
|
45 |
-
*/
|
46 |
-
class TripleDES extends DES
|
47 |
-
{
|
48 |
-
/**
|
49 |
-
* Encrypt / decrypt using inner chaining
|
50 |
-
*
|
51 |
-
* Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (self::MODE_CBC3).
|
52 |
-
*/
|
53 |
-
const MODE_3CBC = -2;
|
54 |
-
|
55 |
-
/**
|
56 |
-
* Encrypt / decrypt using outer chaining
|
57 |
-
*
|
58 |
-
* Outer chaining is used by SSH-2 and when the mode is set to \phpseclib\Crypt\Base::MODE_CBC.
|
59 |
-
*/
|
60 |
-
const MODE_CBC3 = Base::MODE_CBC;
|
61 |
-
|
62 |
-
/**
|
63 |
-
* Key Length (in bytes)
|
64 |
-
*
|
65 |
-
* @see \phpseclib\Crypt\TripleDES::setKeyLength()
|
66 |
-
* @var int
|
67 |
-
* @access private
|
68 |
-
*/
|
69 |
-
var $key_length = 24;
|
70 |
-
|
71 |
-
/**
|
72 |
-
* The default salt used by setPassword()
|
73 |
-
*
|
74 |
-
* @see \phpseclib\Crypt\Base::password_default_salt
|
75 |
-
* @see \phpseclib\Crypt\Base::setPassword()
|
76 |
-
* @var string
|
77 |
-
* @access private
|
78 |
-
*/
|
79 |
-
var $password_default_salt = 'phpseclib';
|
80 |
-
|
81 |
-
/**
|
82 |
-
* The mcrypt specific name of the cipher
|
83 |
-
*
|
84 |
-
* @see \phpseclib\Crypt\DES::cipher_name_mcrypt
|
85 |
-
* @see \phpseclib\Crypt\Base::cipher_name_mcrypt
|
86 |
-
* @var string
|
87 |
-
* @access private
|
88 |
-
*/
|
89 |
-
var $cipher_name_mcrypt = 'tripledes';
|
90 |
-
|
91 |
-
/**
|
92 |
-
* Optimizing value while CFB-encrypting
|
93 |
-
*
|
94 |
-
* @see \phpseclib\Crypt\Base::cfb_init_len
|
95 |
-
* @var int
|
96 |
-
* @access private
|
97 |
-
*/
|
98 |
-
var $cfb_init_len = 750;
|
99 |
-
|
100 |
-
/**
|
101 |
-
* max possible size of $key
|
102 |
-
*
|
103 |
-
* @see self::setKey()
|
104 |
-
* @see \phpseclib\Crypt\DES::setKey()
|
105 |
-
* @var string
|
106 |
-
* @access private
|
107 |
-
*/
|
108 |
-
var $key_length_max = 24;
|
109 |
-
|
110 |
-
/**
|
111 |
-
* Internal flag whether using self::MODE_3CBC or not
|
112 |
-
*
|
113 |
-
* @var bool
|
114 |
-
* @access private
|
115 |
-
*/
|
116 |
-
var $mode_3cbc;
|
117 |
-
|
118 |
-
/**
|
119 |
-
* The \phpseclib\Crypt\DES objects
|
120 |
-
*
|
121 |
-
* Used only if $mode_3cbc === true
|
122 |
-
*
|
123 |
-
* @var array
|
124 |
-
* @access private
|
125 |
-
*/
|
126 |
-
var $des;
|
127 |
-
|
128 |
-
/**
|
129 |
-
* Default Constructor.
|
130 |
-
*
|
131 |
-
* Determines whether or not the mcrypt extension should be used.
|
132 |
-
*
|
133 |
-
* $mode could be:
|
134 |
-
*
|
135 |
-
* - \phpseclib\Crypt\Base::MODE_ECB
|
136 |
-
*
|
137 |
-
* - \phpseclib\Crypt\Base::MODE_CBC
|
138 |
-
*
|
139 |
-
* - \phpseclib\Crypt\Base::MODE_CTR
|
140 |
-
*
|
141 |
-
* - \phpseclib\Crypt\Base::MODE_CFB
|
142 |
-
*
|
143 |
-
* - \phpseclib\Crypt\Base::MODE_OFB
|
144 |
-
*
|
145 |
-
* - \phpseclib\Crypt\TripleDES::MODE_3CBC
|
146 |
-
*
|
147 |
-
* If not explicitly set, \phpseclib\Crypt\Base::MODE_CBC will be used.
|
148 |
-
*
|
149 |
-
* @see \phpseclib\Crypt\DES::__construct()
|
150 |
-
* @see \phpseclib\Crypt\Base::__construct()
|
151 |
-
* @param int $mode
|
152 |
-
* @access public
|
153 |
-
*/
|
154 |
-
function __construct($mode = Base::MODE_CBC)
|
155 |
-
{
|
156 |
-
switch ($mode) {
|
157 |
-
// In case of self::MODE_3CBC, we init as CRYPT_DES_MODE_CBC
|
158 |
-
// and additional flag us internally as 3CBC
|
159 |
-
case self::MODE_3CBC:
|
160 |
-
parent::__construct(Base::MODE_CBC);
|
161 |
-
$this->mode_3cbc = true;
|
162 |
-
|
163 |
-
// This three $des'es will do the 3CBC work (if $key > 64bits)
|
164 |
-
$this->des = array(
|
165 |
-
new DES(Base::MODE_CBC),
|
166 |
-
new DES(Base::MODE_CBC),
|
167 |
-
new DES(Base::MODE_CBC),
|
168 |
-
);
|
169 |
-
|
170 |
-
// we're going to be doing the padding, ourselves, so disable it in the \phpseclib\Crypt\DES objects
|
171 |
-
$this->des[0]->disablePadding();
|
172 |
-
$this->des[1]->disablePadding();
|
173 |
-
$this->des[2]->disablePadding();
|
174 |
-
break;
|
175 |
-
// If not 3CBC, we init as usual
|
176 |
-
default:
|
177 |
-
parent::__construct($mode);
|
178 |
-
}
|
179 |
-
}
|
180 |
-
|
181 |
-
/**
|
182 |
-
* Test for engine validity
|
183 |
-
*
|
184 |
-
* This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine()
|
185 |
-
*
|
186 |
-
* @see \phpseclib\Crypt\Base::__construct()
|
187 |
-
* @param int $engine
|
188 |
-
* @access public
|
189 |
-
* @return bool
|
190 |
-
*/
|
191 |
-
function isValidEngine($engine)
|
192 |
-
{
|
193 |
-
if ($engine == self::ENGINE_OPENSSL) {
|
194 |
-
$this->cipher_name_openssl_ecb = 'des-ede3';
|
195 |
-
$mode = $this->_openssl_translate_mode();
|
196 |
-
$this->cipher_name_openssl = $mode == 'ecb' ? 'des-ede3' : 'des-ede3-' . $mode;
|
197 |
-
}
|
198 |
-
|
199 |
-
return parent::isValidEngine($engine);
|
200 |
-
}
|
201 |
-
|
202 |
-
/**
|
203 |
-
* Sets the initialization vector. (optional)
|
204 |
-
*
|
205 |
-
* SetIV is not required when \phpseclib\Crypt\Base::MODE_ECB is being used. If not explicitly set, it'll be assumed
|
206 |
-
* to be all zero's.
|
207 |
-
*
|
208 |
-
* @see \phpseclib\Crypt\Base::setIV()
|
209 |
-
* @access public
|
210 |
-
* @param string $iv
|
211 |
-
*/
|
212 |
-
function setIV($iv)
|
213 |
-
{
|
214 |
-
parent::setIV($iv);
|
215 |
-
if ($this->mode_3cbc) {
|
216 |
-
$this->des[0]->setIV($iv);
|
217 |
-
$this->des[1]->setIV($iv);
|
218 |
-
$this->des[2]->setIV($iv);
|
219 |
-
}
|
220 |
-
}
|
221 |
-
|
222 |
-
/**
|
223 |
-
* Sets the key length.
|
224 |
-
*
|
225 |
-
* Valid key lengths are 64, 128 and 192
|
226 |
-
*
|
227 |
-
* @see \phpseclib\Crypt\Base:setKeyLength()
|
228 |
-
* @access public
|
229 |
-
* @param int $length
|
230 |
-
*/
|
231 |
-
function setKeyLength($length)
|
232 |
-
{
|
233 |
-
$length >>= 3;
|
234 |
-
switch (true) {
|
235 |
-
case $length <= 8:
|
236 |
-
$this->key_length = 8;
|
237 |
-
break;
|
238 |
-
case $length <= 16:
|
239 |
-
$this->key_length = 16;
|
240 |
-
break;
|
241 |
-
default:
|
242 |
-
$this->key_length = 24;
|
243 |
-
}
|
244 |
-
|
245 |
-
parent::setKeyLength($length);
|
246 |
-
}
|
247 |
-
|
248 |
-
/**
|
249 |
-
* Sets the key.
|
250 |
-
*
|
251 |
-
* Keys can be of any length. Triple DES, itself, can use 128-bit (eg. strlen($key) == 16) or
|
252 |
-
* 192-bit (eg. strlen($key) == 24) keys. This function pads and truncates $key as appropriate.
|
253 |
-
*
|
254 |
-
* DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
|
255 |
-
*
|
256 |
-
* If the key is not explicitly set, it'll be assumed to be all null bytes.
|
257 |
-
*
|
258 |
-
* @access public
|
259 |
-
* @see \phpseclib\Crypt\DES::setKey()
|
260 |
-
* @see \phpseclib\Crypt\Base::setKey()
|
261 |
-
* @param string $key
|
262 |
-
*/
|
263 |
-
function setKey($key)
|
264 |
-
{
|
265 |
-
$length = $this->explicit_key_length ? $this->key_length : strlen($key);
|
266 |
-
if ($length > 8) {
|
267 |
-
$key = str_pad(substr($key, 0, 24), 24, chr(0));
|
268 |
-
// if $key is between 64 and 128-bits, use the first 64-bits as the last, per this:
|
269 |
-
// http://php.net/function.mcrypt-encrypt#47973
|
270 |
-
$key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24);
|
271 |
-
} else {
|
272 |
-
$key = str_pad($key, 8, chr(0));
|
273 |
-
}
|
274 |
-
parent::setKey($key);
|
275 |
-
|
276 |
-
// And in case of self::MODE_3CBC:
|
277 |
-
// if key <= 64bits we not need the 3 $des to work,
|
278 |
-
// because we will then act as regular DES-CBC with just a <= 64bit key.
|
279 |
-
// So only if the key > 64bits (> 8 bytes) we will call setKey() for the 3 $des.
|
280 |
-
if ($this->mode_3cbc && $length > 8) {
|
281 |
-
$this->des[0]->setKey(substr($key, 0, 8));
|
282 |
-
$this->des[1]->setKey(substr($key, 8, 8));
|
283 |
-
$this->des[2]->setKey(substr($key, 16, 8));
|
284 |
-
}
|
285 |
-
}
|
286 |
-
|
287 |
-
/**
|
288 |
-
* Encrypts a message.
|
289 |
-
*
|
290 |
-
* @see \phpseclib\Crypt\Base::encrypt()
|
291 |
-
* @access public
|
292 |
-
* @param string $plaintext
|
293 |
-
* @return string $cipertext
|
294 |
-
*/
|
295 |
-
function encrypt($plaintext)
|
296 |
-
{
|
297 |
-
// parent::en/decrypt() is able to do all the work for all modes and keylengths,
|
298 |
-
// except for: self::MODE_3CBC (inner chaining CBC) with a key > 64bits
|
299 |
-
|
300 |
-
// if the key is smaller then 8, do what we'd normally do
|
301 |
-
if ($this->mode_3cbc && strlen($this->key) > 8) {
|
302 |
-
return $this->des[2]->encrypt(
|
303 |
-
$this->des[1]->decrypt(
|
304 |
-
$this->des[0]->encrypt(
|
305 |
-
$this->_pad($plaintext)
|
306 |
-
)
|
307 |
-
)
|
308 |
-
);
|
309 |
-
}
|
310 |
-
|
311 |
-
return parent::encrypt($plaintext);
|
312 |
-
}
|
313 |
-
|
314 |
-
/**
|
315 |
-
* Decrypts a message.
|
316 |
-
*
|
317 |
-
* @see \phpseclib\Crypt\Base::decrypt()
|
318 |
-
* @access public
|
319 |
-
* @param string $ciphertext
|
320 |
-
* @return string $plaintext
|
321 |
-
*/
|
322 |
-
function decrypt($ciphertext)
|
323 |
-
{
|
324 |
-
if ($this->mode_3cbc && strlen($this->key) > 8) {
|
325 |
-
return $this->_unpad(
|
326 |
-
$this->des[0]->decrypt(
|
327 |
-
$this->des[1]->encrypt(
|
328 |
-
$this->des[2]->decrypt(
|
329 |
-
str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, "\0")
|
330 |
-
)
|
331 |
-
)
|
332 |
-
)
|
333 |
-
);
|
334 |
-
}
|
335 |
-
|
336 |
-
return parent::decrypt($ciphertext);
|
337 |
-
}
|
338 |
-
|
339 |
-
/**
|
340 |
-
* Treat consecutive "packets" as if they are a continuous buffer.
|
341 |
-
*
|
342 |
-
* Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets
|
343 |
-
* will yield different outputs:
|
344 |
-
*
|
345 |
-
* <code>
|
346 |
-
* echo $des->encrypt(substr($plaintext, 0, 8));
|
347 |
-
* echo $des->encrypt(substr($plaintext, 8, 8));
|
348 |
-
* </code>
|
349 |
-
* <code>
|
350 |
-
* echo $des->encrypt($plaintext);
|
351 |
-
* </code>
|
352 |
-
*
|
353 |
-
* The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
|
354 |
-
* another, as demonstrated with the following:
|
355 |
-
*
|
356 |
-
* <code>
|
357 |
-
* $des->encrypt(substr($plaintext, 0, 8));
|
358 |
-
* echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
|
359 |
-
* </code>
|
360 |
-
* <code>
|
361 |
-
* echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
|
362 |
-
* </code>
|
363 |
-
*
|
364 |
-
* With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
|
365 |
-
* outputs. The reason is due to the fact that the initialization vector's change after every encryption /
|
366 |
-
* decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
|
367 |
-
*
|
368 |
-
* Put another way, when the continuous buffer is enabled, the state of the \phpseclib\Crypt\DES() object changes after each
|
369 |
-
* encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
|
370 |
-
* continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
|
371 |
-
* however, they are also less intuitive and more likely to cause you problems.
|
372 |
-
*
|
373 |
-
* @see \phpseclib\Crypt\Base::enableContinuousBuffer()
|
374 |
-
* @see self::disableContinuousBuffer()
|
375 |
-
* @access public
|
376 |
-
*/
|
377 |
-
function enableContinuousBuffer()
|
378 |
-
{
|
379 |
-
parent::enableContinuousBuffer();
|
380 |
-
if ($this->mode_3cbc) {
|
381 |
-
$this->des[0]->enableContinuousBuffer();
|
382 |
-
$this->des[1]->enableContinuousBuffer();
|
383 |
-
$this->des[2]->enableContinuousBuffer();
|
384 |
-
}
|
385 |
-
}
|
386 |
-
|
387 |
-
/**
|
388 |
-
* Treat consecutive packets as if they are a discontinuous buffer.
|
389 |
-
*
|
390 |
-
* The default behavior.
|
391 |
-
*
|
392 |
-
* @see \phpseclib\Crypt\Base::disableContinuousBuffer()
|
393 |
-
* @see self::enableContinuousBuffer()
|
394 |
-
* @access public
|
395 |
-
*/
|
396 |
-
function disableContinuousBuffer()
|
397 |
-
{
|
398 |
-
parent::disableContinuousBuffer();
|
399 |
-
if ($this->mode_3cbc) {
|
400 |
-
$this->des[0]->disableContinuousBuffer();
|
401 |
-
$this->des[1]->disableContinuousBuffer();
|
402 |
-
$this->des[2]->disableContinuousBuffer();
|
403 |
-
}
|
404 |
-
}
|
405 |
-
|
406 |
-
/**
|
407 |
-
* Creates the key schedule
|
408 |
-
*
|
409 |
-
* @see \phpseclib\Crypt\DES::_setupKey()
|
410 |
-
* @see \phpseclib\Crypt\Base::_setupKey()
|
411 |
-
* @access private
|
412 |
-
*/
|
413 |
-
function _setupKey()
|
414 |
-
{
|
415 |
-
switch (true) {
|
416 |
-
// if $key <= 64bits we configure our internal pure-php cipher engine
|
417 |
-
// to act as regular [1]DES, not as 3DES. mcrypt.so::tripledes does the same.
|
418 |
-
case strlen($this->key) <= 8:
|
419 |
-
$this->des_rounds = 1;
|
420 |
-
break;
|
421 |
-
|
422 |
-
// otherwise, if $key > 64bits, we configure our engine to work as 3DES.
|
423 |
-
default:
|
424 |
-
$this->des_rounds = 3;
|
425 |
-
|
426 |
-
// (only) if 3CBC is used we have, of course, to setup the $des[0-2] keys also separately.
|
427 |
-
if ($this->mode_3cbc) {
|
428 |
-
$this->des[0]->_setupKey();
|
429 |
-
$this->des[1]->_setupKey();
|
430 |
-
$this->des[2]->_setupKey();
|
431 |
-
|
432 |
-
// because $des[0-2] will, now, do all the work we can return here
|
433 |
-
// not need unnecessary stress parent::_setupKey() with our, now unused, $key.
|
434 |
-
return;
|
435 |
-
}
|
436 |
-
}
|
437 |
-
// setup our key
|
438 |
-
parent::_setupKey();
|
439 |
-
}
|
440 |
-
|
441 |
-
/**
|
442 |
-
* Sets the internal crypt engine
|
443 |
-
*
|
444 |
-
* @see \phpseclib\Crypt\Base::__construct()
|
445 |
-
* @see \phpseclib\Crypt\Base::setPreferredEngine()
|
446 |
-
* @param int $engine
|
447 |
-
* @access public
|
448 |
-
* @return int
|
449 |
-
*/
|
450 |
-
function setPreferredEngine($engine)
|
451 |
-
{
|
452 |
-
if ($this->mode_3cbc) {
|
453 |
-
$this->des[0]->setPreferredEngine($engine);
|
454 |
-
$this->des[1]->setPreferredEngine($engine);
|
455 |
-
$this->des[2]->setPreferredEngine($engine);
|
456 |
-
}
|
457 |
-
|
458 |
-
return parent::setPreferredEngine($engine);
|
459 |
-
}
|
460 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php
DELETED
@@ -1,808 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Pure-PHP implementation of Twofish.
|
5 |
-
*
|
6 |
-
* Uses mcrypt, if available, and an internal implementation, otherwise.
|
7 |
-
*
|
8 |
-
* PHP version 5
|
9 |
-
*
|
10 |
-
* Useful resources are as follows:
|
11 |
-
*
|
12 |
-
* - {@link http://en.wikipedia.org/wiki/Twofish Wikipedia description of Twofish}
|
13 |
-
*
|
14 |
-
* Here's a short example of how to use this library:
|
15 |
-
* <code>
|
16 |
-
* <?php
|
17 |
-
* include 'vendor/autoload.php';
|
18 |
-
*
|
19 |
-
* $twofish = new \phpseclib\Crypt\Twofish();
|
20 |
-
*
|
21 |
-
* $twofish->setKey('12345678901234567890123456789012');
|
22 |
-
*
|
23 |
-
* $plaintext = str_repeat('a', 1024);
|
24 |
-
*
|
25 |
-
* echo $twofish->decrypt($twofish->encrypt($plaintext));
|
26 |
-
* ?>
|
27 |
-
* </code>
|
28 |
-
*
|
29 |
-
* @category Crypt
|
30 |
-
* @package Twofish
|
31 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
32 |
-
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
|
33 |
-
* @copyright 2007 Jim Wigginton
|
34 |
-
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
35 |
-
* @link http://phpseclib.sourceforge.net
|
36 |
-
*/
|
37 |
-
|
38 |
-
namespace phpseclib\Crypt;
|
39 |
-
|
40 |
-
/**
|
41 |
-
* Pure-PHP implementation of Twofish.
|
42 |
-
*
|
43 |
-
* @package Twofish
|
44 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
45 |
-
* @author Hans-Juergen Petrich <petrich@tronic-media.com>
|
46 |
-
* @access public
|
47 |
-
*/
|
48 |
-
class Twofish extends Base
|
49 |
-
{
|
50 |
-
/**
|
51 |
-
* The mcrypt specific name of the cipher
|
52 |
-
*
|
53 |
-
* @see \phpseclib\Crypt\Base::cipher_name_mcrypt
|
54 |
-
* @var string
|
55 |
-
* @access private
|
56 |
-
*/
|
57 |
-
var $cipher_name_mcrypt = 'twofish';
|
58 |
-
|
59 |
-
/**
|
60 |
-
* Optimizing value while CFB-encrypting
|
61 |
-
*
|
62 |
-
* @see \phpseclib\Crypt\Base::cfb_init_len
|
63 |
-
* @var int
|
64 |
-
* @access private
|
65 |
-
*/
|
66 |
-
var $cfb_init_len = 800;
|
67 |
-
|
68 |
-
/**
|
69 |
-
* Q-Table
|
70 |
-
*
|
71 |
-
* @var array
|
72 |
-
* @access private
|
73 |
-
*/
|
74 |
-
var $q0 = array(
|
75 |
-
0xA9, 0x67, 0xB3, 0xE8, 0x04, 0xFD, 0xA3, 0x76,
|
76 |
-
0x9A, 0x92, 0x80, 0x78, 0xE4, 0xDD, 0xD1, 0x38,
|
77 |
-
0x0D, 0xC6, 0x35, 0x98, 0x18, 0xF7, 0xEC, 0x6C,
|
78 |
-
0x43, 0x75, 0x37, 0x26, 0xFA, 0x13, 0x94, 0x48,
|
79 |
-
0xF2, 0xD0, 0x8B, 0x30, 0x84, 0x54, 0xDF, 0x23,
|
80 |
-
0x19, 0x5B, 0x3D, 0x59, 0xF3, 0xAE, 0xA2, 0x82,
|
81 |
-
0x63, 0x01, 0x83, 0x2E, 0xD9, 0x51, 0x9B, 0x7C,
|
82 |
-
0xA6, 0xEB, 0xA5, 0xBE, 0x16, 0x0C, 0xE3, 0x61,
|
83 |
-
0xC0, 0x8C, 0x3A, 0xF5, 0x73, 0x2C, 0x25, 0x0B,
|
84 |
-
0xBB, 0x4E, 0x89, 0x6B, 0x53, 0x6A, 0xB4, 0xF1,
|
85 |
-
0xE1, 0xE6, 0xBD, 0x45, 0xE2, 0xF4, 0xB6, 0x66,
|
86 |
-
0xCC, 0x95, 0x03, 0x56, 0xD4, 0x1C, 0x1E, 0xD7,
|
87 |
-
0xFB, 0xC3, 0x8E, 0xB5, 0xE9, 0xCF, 0xBF, 0xBA,
|
88 |
-
0xEA, 0x77, 0x39, 0xAF, 0x33, 0xC9, 0x62, 0x71,
|
89 |
-
0x81, 0x79, 0x09, 0xAD, 0x24, 0xCD, 0xF9, 0xD8,
|
90 |
-
0xE5, 0xC5, 0xB9, 0x4D, 0x44, 0x08, 0x86, 0xE7,
|
91 |
-
0xA1, 0x1D, 0xAA, 0xED, 0x06, 0x70, 0xB2, 0xD2,
|
92 |
-
0x41, 0x7B, 0xA0, 0x11, 0x31, 0xC2, 0x27, 0x90,
|
93 |
-
0x20, 0xF6, 0x60, 0xFF, 0x96, 0x5C, 0xB1, 0xAB,
|
94 |
-
0x9E, 0x9C, 0x52, 0x1B, 0x5F, 0x93, 0x0A, 0xEF,
|
95 |
-
0x91, 0x85, 0x49, 0xEE, 0x2D, 0x4F, 0x8F, 0x3B,
|
96 |
-
0x47, 0x87, 0x6D, 0x46, 0xD6, 0x3E, 0x69, 0x64,
|
97 |
-
0x2A, 0xCE, 0xCB, 0x2F, 0xFC, 0x97, 0x05, 0x7A,
|
98 |
-
0xAC, 0x7F, 0xD5, 0x1A, 0x4B, 0x0E, 0xA7, 0x5A,
|
99 |
-
0x28, 0x14, 0x3F, 0x29, 0x88, 0x3C, 0x4C, 0x02,
|
100 |
-
0xB8, 0xDA, 0xB0, 0x17, 0x55, 0x1F, 0x8A, 0x7D,
|
101 |
-
0x57, 0xC7, 0x8D, 0x74, 0xB7, 0xC4, 0x9F, 0x72,
|
102 |
-
0x7E, 0x15, 0x22, 0x12, 0x58, 0x07, 0x99, 0x34,
|
103 |
-
0x6E, 0x50, 0xDE, 0x68, 0x65, 0xBC, 0xDB, 0xF8,
|
104 |
-
0xC8, 0xA8, 0x2B, 0x40, 0xDC, 0xFE, 0x32, 0xA4,
|
105 |
-
0xCA, 0x10, 0x21, 0xF0, 0xD3, 0x5D, 0x0F, 0x00,
|
106 |
-
0x6F, 0x9D, 0x36, 0x42, 0x4A, 0x5E, 0xC1, 0xE0
|
107 |
-
);
|
108 |
-
|
109 |
-
/**
|
110 |
-
* Q-Table
|
111 |
-
*
|
112 |
-
* @var array
|
113 |
-
* @access private
|
114 |
-
*/
|
115 |
-
var $q1 = array(
|
116 |
-
0x75, 0xF3, 0xC6, 0xF4, 0xDB, 0x7B, 0xFB, 0xC8,
|
117 |
-
0x4A, 0xD3, 0xE6, 0x6B, 0x45, 0x7D, 0xE8, 0x4B,
|
118 |
-
0xD6, 0x32, 0xD8, 0xFD, 0x37, 0x71, 0xF1, 0xE1,
|
119 |
-
0x30, 0x0F, 0xF8, 0x1B, 0x87, 0xFA, 0x06, 0x3F,
|
120 |
-
0x5E, 0xBA, 0xAE, 0x5B, 0x8A, 0x00, 0xBC, 0x9D,
|
121 |
-
0x6D, 0xC1, 0xB1, 0x0E, 0x80, 0x5D, 0xD2, 0xD5,
|
122 |
-
0xA0, 0x84, 0x07, 0x14, 0xB5, 0x90, 0x2C, 0xA3,
|
123 |
-
0xB2, 0x73, 0x4C, 0x54, 0x92, 0x74, 0x36, 0x51,
|
124 |
-
0x38, 0xB0, 0xBD, 0x5A, 0xFC, 0x60, 0x62, 0x96,
|
125 |
-
0x6C, 0x42, 0xF7, 0x10, 0x7C, 0x28, 0x27, 0x8C,
|
126 |
-
0x13, 0x95, 0x9C, 0xC7, 0x24, 0x46, 0x3B, 0x70,
|
127 |
-
0xCA, 0xE3, 0x85, 0xCB, 0x11, 0xD0, 0x93, 0xB8,
|
128 |
-
0xA6, 0x83, 0x20, 0xFF, 0x9F, 0x77, 0xC3, 0xCC,
|
129 |
-
0x03, 0x6F, 0x08, 0xBF, 0x40, 0xE7, 0x2B, 0xE2,
|
130 |
-
0x79, 0x0C, 0xAA, 0x82, 0x41, 0x3A, 0xEA, 0xB9,
|
131 |
-
0xE4, 0x9A, 0xA4, 0x97, 0x7E, 0xDA, 0x7A, 0x17,
|
132 |
-
0x66, 0x94, 0xA1, 0x1D, 0x3D, 0xF0, 0xDE, 0xB3,
|
133 |
-
0x0B, 0x72, 0xA7, 0x1C, 0xEF, 0xD1, 0x53, 0x3E,
|
134 |
-
0x8F, 0x33, 0x26, 0x5F, 0xEC, 0x76, 0x2A, 0x49,
|
135 |
-
0x81, 0x88, 0xEE, 0x21, 0xC4, 0x1A, 0xEB, 0xD9,
|
136 |
-
0xC5, 0x39, 0x99, 0xCD, 0xAD, 0x31, 0x8B, 0x01,
|
137 |
-
0x18, 0x23, 0xDD, 0x1F, 0x4E, 0x2D, 0xF9, 0x48,
|
138 |
-
0x4F, 0xF2, 0x65, 0x8E, 0x78, 0x5C, 0x58, 0x19,
|
139 |
-
0x8D, 0xE5, 0x98, 0x57, 0x67, 0x7F, 0x05, 0x64,
|
140 |
-
0xAF, 0x63, 0xB6, 0xFE, 0xF5, 0xB7, 0x3C, 0xA5,
|
141 |
-
0xCE, 0xE9, 0x68, 0x44, 0xE0, 0x4D, 0x43, 0x69,
|
142 |
-
0x29, 0x2E, 0xAC, 0x15, 0x59, 0xA8, 0x0A, 0x9E,
|
143 |
-
0x6E, 0x47, 0xDF, 0x34, 0x35, 0x6A, 0xCF, 0xDC,
|
144 |
-
0x22, 0xC9, 0xC0, 0x9B, 0x89, 0xD4, 0xED, 0xAB,
|
145 |
-
0x12, 0xA2, 0x0D, 0x52, 0xBB, 0x02, 0x2F, 0xA9,
|
146 |
-
0xD7, 0x61, 0x1E, 0xB4, 0x50, 0x04, 0xF6, 0xC2,
|
147 |
-
0x16, 0x25, 0x86, 0x56, 0x55, 0x09, 0xBE, 0x91
|
148 |
-
);
|
149 |
-
|
150 |
-
/**
|
151 |
-
* M-Table
|
152 |
-
*
|
153 |
-
* @var array
|
154 |
-
* @access private
|
155 |
-
*/
|
156 |
-
var $m0 = array(
|
157 |
-
0xBCBC3275, 0xECEC21F3, 0x202043C6, 0xB3B3C9F4, 0xDADA03DB, 0x02028B7B, 0xE2E22BFB, 0x9E9EFAC8,
|
158 |
-
0xC9C9EC4A, 0xD4D409D3, 0x18186BE6, 0x1E1E9F6B, 0x98980E45, 0xB2B2387D, 0xA6A6D2E8, 0x2626B74B,
|
159 |
-
0x3C3C57D6, 0x93938A32, 0x8282EED8, 0x525298FD, 0x7B7BD437, 0xBBBB3771, 0x5B5B97F1, 0x474783E1,
|
160 |
-
0x24243C30, 0x5151E20F, 0xBABAC6F8, 0x4A4AF31B, 0xBFBF4887, 0x0D0D70FA, 0xB0B0B306, 0x7575DE3F,
|
161 |
-
0xD2D2FD5E, 0x7D7D20BA, 0x666631AE, 0x3A3AA35B, 0x59591C8A, 0x00000000, 0xCDCD93BC, 0x1A1AE09D,
|
162 |
-
0xAEAE2C6D, 0x7F7FABC1, 0x2B2BC7B1, 0xBEBEB90E, 0xE0E0A080, 0x8A8A105D, 0x3B3B52D2, 0x6464BAD5,
|
163 |
-
0xD8D888A0, 0xE7E7A584, 0x5F5FE807, 0x1B1B1114, 0x2C2CC2B5, 0xFCFCB490, 0x3131272C, 0x808065A3,
|
164 |
-
0x73732AB2, 0x0C0C8173, 0x79795F4C, 0x6B6B4154, 0x4B4B0292, 0x53536974, 0x94948F36, 0x83831F51,
|
165 |
-
0x2A2A3638, 0xC4C49CB0, 0x2222C8BD, 0xD5D5F85A, 0xBDBDC3FC, 0x48487860, 0xFFFFCE62, 0x4C4C0796,
|
166 |
-
0x4141776C, 0xC7C7E642, 0xEBEB24F7, 0x1C1C1410, 0x5D5D637C, 0x36362228, 0x6767C027, 0xE9E9AF8C,
|
167 |
-
0x4444F913, 0x1414EA95, 0xF5F5BB9C, 0xCFCF18C7, 0x3F3F2D24, 0xC0C0E346, 0x7272DB3B, 0x54546C70,
|
168 |
-
0x29294CCA, 0xF0F035E3, 0x0808FE85, 0xC6C617CB, 0xF3F34F11, 0x8C8CE4D0, 0xA4A45993, 0xCACA96B8,
|
169 |
-
0x68683BA6, 0xB8B84D83, 0x38382820, 0xE5E52EFF, 0xADAD569F, 0x0B0B8477, 0xC8C81DC3, 0x9999FFCC,
|
170 |
-
0x5858ED03, 0x19199A6F, 0x0E0E0A08, 0x95957EBF, 0x70705040, 0xF7F730E7, 0x6E6ECF2B, 0x1F1F6EE2,
|
171 |
-
0xB5B53D79, 0x09090F0C, 0x616134AA, 0x57571682, 0x9F9F0B41, 0x9D9D803A, 0x111164EA, 0x2525CDB9,
|
172 |
-
0xAFAFDDE4, 0x4545089A, 0xDFDF8DA4, 0xA3A35C97, 0xEAEAD57E, 0x353558DA, 0xEDEDD07A, 0x4343FC17,
|
173 |
-
0xF8F8CB66, 0xFBFBB194, 0x3737D3A1, 0xFAFA401D, 0xC2C2683D, 0xB4B4CCF0, 0x32325DDE, 0x9C9C71B3,
|
174 |
-
0x5656E70B, 0xE3E3DA72, 0x878760A7, 0x15151B1C, 0xF9F93AEF, 0x6363BFD1, 0x3434A953, 0x9A9A853E,
|
175 |
-
0xB1B1428F, 0x7C7CD133, 0x88889B26, 0x3D3DA65F, 0xA1A1D7EC, 0xE4E4DF76, 0x8181942A, 0x91910149,
|
176 |
-
0x0F0FFB81, 0xEEEEAA88, 0x161661EE, 0xD7D77321, 0x9797F5C4, 0xA5A5A81A, 0xFEFE3FEB, 0x6D6DB5D9,
|
177 |
-
0x7878AEC5, 0xC5C56D39, 0x1D1DE599, 0x7676A4CD, 0x3E3EDCAD, 0xCBCB6731, 0xB6B6478B, 0xEFEF5B01,
|
178 |
-
0x12121E18, 0x6060C523, 0x6A6AB0DD, 0x4D4DF61F, 0xCECEE94E, 0xDEDE7C2D, 0x55559DF9, 0x7E7E5A48,
|
179 |
-
0x2121B24F, 0x03037AF2, 0xA0A02665, 0x5E5E198E, 0x5A5A6678, 0x65654B5C, 0x62624E58, 0xFDFD4519,
|
180 |
-
0x0606F48D, 0x404086E5, 0xF2F2BE98, 0x3333AC57, 0x17179067, 0x05058E7F, 0xE8E85E05, 0x4F4F7D64,
|
181 |
-
0x89896AAF, 0x10109563, 0x74742FB6, 0x0A0A75FE, 0x5C5C92F5, 0x9B9B74B7, 0x2D2D333C, 0x3030D6A5,
|
182 |
-
0x2E2E49CE, 0x494989E9, 0x46467268, 0x77775544, 0xA8A8D8E0, 0x9696044D, 0x2828BD43, 0xA9A92969,
|
183 |
-
0xD9D97929, 0x8686912E, 0xD1D187AC, 0xF4F44A15, 0x8D8D1559, 0xD6D682A8, 0xB9B9BC0A, 0x42420D9E,
|
184 |
-
0xF6F6C16E, 0x2F2FB847, 0xDDDD06DF, 0x23233934, 0xCCCC6235, 0xF1F1C46A, 0xC1C112CF, 0x8585EBDC,
|
185 |
-
0x8F8F9E22, 0x7171A1C9, 0x9090F0C0, 0xAAAA539B, 0x0101F189, 0x8B8BE1D4, 0x4E4E8CED, 0x8E8E6FAB,
|
186 |
-
0xABABA212, 0x6F6F3EA2, 0xE6E6540D, 0xDBDBF252, 0x92927BBB, 0xB7B7B602, 0x6969CA2F, 0x3939D9A9,
|
187 |
-
0xD3D30CD7, 0xA7A72361, 0xA2A2AD1E, 0xC3C399B4, 0x6C6C4450, 0x07070504, 0x04047FF6, 0x272746C2,
|
188 |
-
0xACACA716, 0xD0D07625, 0x50501386, 0xDCDCF756, 0x84841A55, 0xE1E15109, 0x7A7A25BE, 0x1313EF91
|
189 |
-
);
|
190 |
-
|
191 |
-
/**
|
192 |
-
* M-Table
|
193 |
-
*
|
194 |
-
* @var array
|
195 |
-
* @access private
|
196 |
-
*/
|
197 |
-
var $m1 = array(
|
198 |
-
0xA9D93939, 0x67901717, 0xB3719C9C, 0xE8D2A6A6, 0x04050707, 0xFD985252, 0xA3658080, 0x76DFE4E4,
|
199 |
-
0x9A084545, 0x92024B4B, 0x80A0E0E0, 0x78665A5A, 0xE4DDAFAF, 0xDDB06A6A, 0xD1BF6363, 0x38362A2A,
|
200 |
-
0x0D54E6E6, 0xC6432020, 0x3562CCCC, 0x98BEF2F2, 0x181E1212, 0xF724EBEB, 0xECD7A1A1, 0x6C774141,
|
201 |
-
0x43BD2828, 0x7532BCBC, 0x37D47B7B, 0x269B8888, 0xFA700D0D, 0x13F94444, 0x94B1FBFB, 0x485A7E7E,
|
202 |
-
0xF27A0303, 0xD0E48C8C, 0x8B47B6B6, 0x303C2424, 0x84A5E7E7, 0x54416B6B, 0xDF06DDDD, 0x23C56060,
|
203 |
-
0x1945FDFD, 0x5BA33A3A, 0x3D68C2C2, 0x59158D8D, 0xF321ECEC, 0xAE316666, 0xA23E6F6F, 0x82165757,
|
204 |
-
0x63951010, 0x015BEFEF, 0x834DB8B8, 0x2E918686, 0xD9B56D6D, 0x511F8383, 0x9B53AAAA, 0x7C635D5D,
|
205 |
-
0xA63B6868, 0xEB3FFEFE, 0xA5D63030, 0xBE257A7A, 0x16A7ACAC, 0x0C0F0909, 0xE335F0F0, 0x6123A7A7,
|
206 |
-
0xC0F09090, 0x8CAFE9E9, 0x3A809D9D, 0xF5925C5C, 0x73810C0C, 0x2C273131, 0x2576D0D0, 0x0BE75656,
|
207 |
-
0xBB7B9292, 0x4EE9CECE, 0x89F10101, 0x6B9F1E1E, 0x53A93434, 0x6AC4F1F1, 0xB499C3C3, 0xF1975B5B,
|
208 |
-
0xE1834747, 0xE66B1818, 0xBDC82222, 0x450E9898, 0xE26E1F1F, 0xF4C9B3B3, 0xB62F7474, 0x66CBF8F8,
|
209 |
-
0xCCFF9999, 0x95EA1414, 0x03ED5858, 0x56F7DCDC, 0xD4E18B8B, 0x1C1B1515, 0x1EADA2A2, 0xD70CD3D3,
|
210 |
-
0xFB2BE2E2, 0xC31DC8C8, 0x8E195E5E, 0xB5C22C2C, 0xE9894949, 0xCF12C1C1, 0xBF7E9595, 0xBA207D7D,
|
211 |
-
0xEA641111, 0x77840B0B, 0x396DC5C5, 0xAF6A8989, 0x33D17C7C, 0xC9A17171, 0x62CEFFFF, 0x7137BBBB,
|
212 |
-
0x81FB0F0F, 0x793DB5B5, 0x0951E1E1, 0xADDC3E3E, 0x242D3F3F, 0xCDA47676, 0xF99D5555, 0xD8EE8282,
|
213 |
-
0xE5864040, 0xC5AE7878, 0xB9CD2525, 0x4D049696, 0x44557777, 0x080A0E0E, 0x86135050, 0xE730F7F7,
|
214 |
-
0xA1D33737, 0x1D40FAFA, 0xAA346161, 0xED8C4E4E, 0x06B3B0B0, 0x706C5454, 0xB22A7373, 0xD2523B3B,
|
215 |
-
0x410B9F9F, 0x7B8B0202, 0xA088D8D8, 0x114FF3F3, 0x3167CBCB, 0xC2462727, 0x27C06767, 0x90B4FCFC,
|
216 |
-
0x20283838, 0xF67F0404, 0x60784848, 0xFF2EE5E5, 0x96074C4C, 0x5C4B6565, 0xB1C72B2B, 0xAB6F8E8E,
|
217 |
-
0x9E0D4242, 0x9CBBF5F5, 0x52F2DBDB, 0x1BF34A4A, 0x5FA63D3D, 0x9359A4A4, 0x0ABCB9B9, 0xEF3AF9F9,
|
218 |
-
0x91EF1313, 0x85FE0808, 0x49019191, 0xEE611616, 0x2D7CDEDE, 0x4FB22121, 0x8F42B1B1, 0x3BDB7272,
|
219 |
-
0x47B82F2F, 0x8748BFBF, 0x6D2CAEAE, 0x46E3C0C0, 0xD6573C3C, 0x3E859A9A, 0x6929A9A9, 0x647D4F4F,
|
220 |
-
0x2A948181, 0xCE492E2E, 0xCB17C6C6, 0x2FCA6969, 0xFCC3BDBD, 0x975CA3A3, 0x055EE8E8, 0x7AD0EDED,
|
221 |
-
0xAC87D1D1, 0x7F8E0505, 0xD5BA6464, 0x1AA8A5A5, 0x4BB72626, 0x0EB9BEBE, 0xA7608787, 0x5AF8D5D5,
|
222 |
-
0x28223636, 0x14111B1B, 0x3FDE7575, 0x2979D9D9, 0x88AAEEEE, 0x3C332D2D, 0x4C5F7979, 0x02B6B7B7,
|
223 |
-
0xB896CACA, 0xDA583535, 0xB09CC4C4, 0x17FC4343, 0x551A8484, 0x1FF64D4D, 0x8A1C5959, 0x7D38B2B2,
|
224 |
-
0x57AC3333, 0xC718CFCF, 0x8DF40606, 0x74695353, 0xB7749B9B, 0xC4F59797, 0x9F56ADAD, 0x72DAE3E3,
|
225 |
-
0x7ED5EAEA, 0x154AF4F4, 0x229E8F8F, 0x12A2ABAB, 0x584E6262, 0x07E85F5F, 0x99E51D1D, 0x34392323,
|
226 |
-
0x6EC1F6F6, 0x50446C6C, 0xDE5D3232, 0x68724646, 0x6526A0A0, 0xBC93CDCD, 0xDB03DADA, 0xF8C6BABA,
|
227 |
-
0xC8FA9E9E, 0xA882D6D6, 0x2BCF6E6E, 0x40507070, 0xDCEB8585, 0xFE750A0A, 0x328A9393, 0xA48DDFDF,
|
228 |
-
0xCA4C2929, 0x10141C1C, 0x2173D7D7, 0xF0CCB4B4, 0xD309D4D4, 0x5D108A8A, 0x0FE25151, 0x00000000,
|
229 |
-
0x6F9A1919, 0x9DE01A1A, 0x368F9494, 0x42E6C7C7, 0x4AECC9C9, 0x5EFDD2D2, 0xC1AB7F7F, 0xE0D8A8A8
|
230 |
-
);
|
231 |
-
|
232 |
-
/**
|
233 |
-
* M-Table
|
234 |
-
*
|
235 |
-
* @var array
|
236 |
-
* @access private
|
237 |
-
*/
|
238 |
-
var $m2 = array(
|
239 |
-
0xBC75BC32, 0xECF3EC21, 0x20C62043, 0xB3F4B3C9, 0xDADBDA03, 0x027B028B, 0xE2FBE22B, 0x9EC89EFA,
|
240 |
-
0xC94AC9EC, 0xD4D3D409, 0x18E6186B, 0x1E6B1E9F, 0x9845980E, 0xB27DB238, 0xA6E8A6D2, 0x264B26B7,
|
241 |
-
0x3CD63C57, 0x9332938A, 0x82D882EE, 0x52FD5298, 0x7B377BD4, 0xBB71BB37, 0x5BF15B97, 0x47E14783,
|
242 |
-
0x2430243C, 0x510F51E2, 0xBAF8BAC6, 0x4A1B4AF3, 0xBF87BF48, 0x0DFA0D70, 0xB006B0B3, 0x753F75DE,
|
243 |
-
0xD25ED2FD, 0x7DBA7D20, 0x66AE6631, 0x3A5B3AA3, 0x598A591C, 0x00000000, 0xCDBCCD93, 0x1A9D1AE0,
|
244 |
-
0xAE6DAE2C, 0x7FC17FAB, 0x2BB12BC7, 0xBE0EBEB9, 0xE080E0A0, 0x8A5D8A10, 0x3BD23B52, 0x64D564BA,
|
245 |
-
0xD8A0D888, 0xE784E7A5, 0x5F075FE8, 0x1B141B11, 0x2CB52CC2, 0xFC90FCB4, 0x312C3127, 0x80A38065,
|
246 |
-
0x73B2732A, 0x0C730C81, 0x794C795F, 0x6B546B41, 0x4B924B02, 0x53745369, 0x9436948F, 0x8351831F,
|
247 |
-
0x2A382A36, 0xC4B0C49C, 0x22BD22C8, 0xD55AD5F8, 0xBDFCBDC3, 0x48604878, 0xFF62FFCE, 0x4C964C07,
|
248 |
-
0x416C4177, 0xC742C7E6, 0xEBF7EB24, 0x1C101C14, 0x5D7C5D63, 0x36283622, 0x672767C0, 0xE98CE9AF,
|
249 |
-
0x441344F9, 0x149514EA, 0xF59CF5BB, 0xCFC7CF18, 0x3F243F2D, 0xC046C0E3, 0x723B72DB, 0x5470546C,
|
250 |
-
0x29CA294C, 0xF0E3F035, 0x088508FE, 0xC6CBC617, 0xF311F34F, 0x8CD08CE4, 0xA493A459, 0xCAB8CA96,
|
251 |
-
0x68A6683B, 0xB883B84D, 0x38203828, 0xE5FFE52E, 0xAD9FAD56, 0x0B770B84, 0xC8C3C81D, 0x99CC99FF,
|
252 |
-
0x580358ED, 0x196F199A, 0x0E080E0A, 0x95BF957E, 0x70407050, 0xF7E7F730, 0x6E2B6ECF, 0x1FE21F6E,
|
253 |
-
0xB579B53D, 0x090C090F, 0x61AA6134, 0x57825716, 0x9F419F0B, 0x9D3A9D80, 0x11EA1164, 0x25B925CD,
|
254 |
-
0xAFE4AFDD, 0x459A4508, 0xDFA4DF8D, 0xA397A35C, 0xEA7EEAD5, 0x35DA3558, 0xED7AEDD0, 0x431743FC,
|
255 |
-
0xF866F8CB, 0xFB94FBB1, 0x37A137D3, 0xFA1DFA40, 0xC23DC268, 0xB4F0B4CC, 0x32DE325D, 0x9CB39C71,
|
256 |
-
0x560B56E7, 0xE372E3DA, 0x87A78760, 0x151C151B, 0xF9EFF93A, 0x63D163BF, 0x345334A9, 0x9A3E9A85,
|
257 |
-
0xB18FB142, 0x7C337CD1, 0x8826889B, 0x3D5F3DA6, 0xA1ECA1D7, 0xE476E4DF, 0x812A8194, 0x91499101,
|
258 |
-
0x0F810FFB, 0xEE88EEAA, 0x16EE1661, 0xD721D773, 0x97C497F5, 0xA51AA5A8, 0xFEEBFE3F, 0x6DD96DB5,
|
259 |
-
0x78C578AE, 0xC539C56D, 0x1D991DE5, 0x76CD76A4, 0x3EAD3EDC, 0xCB31CB67, 0xB68BB647, 0xEF01EF5B,
|
260 |
-
0x1218121E, 0x602360C5, 0x6ADD6AB0, 0x4D1F4DF6, 0xCE4ECEE9, 0xDE2DDE7C, 0x55F9559D, 0x7E487E5A,
|
261 |
-
0x214F21B2, 0x03F2037A, 0xA065A026, 0x5E8E5E19, 0x5A785A66, 0x655C654B, 0x6258624E, 0xFD19FD45,
|
262 |
-
0x068D06F4, 0x40E54086, 0xF298F2BE, 0x335733AC, 0x17671790, 0x057F058E, 0xE805E85E, 0x4F644F7D,
|
263 |
-
0x89AF896A, 0x10631095, 0x74B6742F, 0x0AFE0A75, 0x5CF55C92, 0x9BB79B74, 0x2D3C2D33, 0x30A530D6,
|
264 |
-
0x2ECE2E49, 0x49E94989, 0x46684672, 0x77447755, 0xA8E0A8D8, 0x964D9604, 0x284328BD, 0xA969A929,
|
265 |
-
0xD929D979, 0x862E8691, 0xD1ACD187, 0xF415F44A, 0x8D598D15, 0xD6A8D682, 0xB90AB9BC, 0x429E420D,
|
266 |
-
0xF66EF6C1, 0x2F472FB8, 0xDDDFDD06, 0x23342339, 0xCC35CC62, 0xF16AF1C4, 0xC1CFC112, 0x85DC85EB,
|
267 |
-
0x8F228F9E, 0x71C971A1, 0x90C090F0, 0xAA9BAA53, 0x018901F1, 0x8BD48BE1, 0x4EED4E8C, 0x8EAB8E6F,
|
268 |
-
0xAB12ABA2, 0x6FA26F3E, 0xE60DE654, 0xDB52DBF2, 0x92BB927B, 0xB702B7B6, 0x692F69CA, 0x39A939D9,
|
269 |
-
0xD3D7D30C, 0xA761A723, 0xA21EA2AD, 0xC3B4C399, 0x6C506C44, 0x07040705, 0x04F6047F, 0x27C22746,
|
270 |
-
0xAC16ACA7, 0xD025D076, 0x50865013, 0xDC56DCF7, 0x8455841A, 0xE109E151, 0x7ABE7A25, 0x139113EF
|
271 |
-
);
|
272 |
-
|
273 |
-
/**
|
274 |
-
* M-Table
|
275 |
-
*
|
276 |
-
* @var array
|
277 |
-
* @access private
|
278 |
-
*/
|
279 |
-
var $m3 = array(
|
280 |
-
0xD939A9D9, 0x90176790, 0x719CB371, 0xD2A6E8D2, 0x05070405, 0x9852FD98, 0x6580A365, 0xDFE476DF,
|
281 |
-
0x08459A08, 0x024B9202, 0xA0E080A0, 0x665A7866, 0xDDAFE4DD, 0xB06ADDB0, 0xBF63D1BF, 0x362A3836,
|
282 |
-
0x54E60D54, 0x4320C643, 0x62CC3562, 0xBEF298BE, 0x1E12181E, 0x24EBF724, 0xD7A1ECD7, 0x77416C77,
|
283 |
-
0xBD2843BD, 0x32BC7532, 0xD47B37D4, 0x9B88269B, 0x700DFA70, 0xF94413F9, 0xB1FB94B1, 0x5A7E485A,
|
284 |
-
0x7A03F27A, 0xE48CD0E4, 0x47B68B47, 0x3C24303C, 0xA5E784A5, 0x416B5441, 0x06DDDF06, 0xC56023C5,
|
285 |
-
0x45FD1945, 0xA33A5BA3, 0x68C23D68, 0x158D5915, 0x21ECF321, 0x3166AE31, 0x3E6FA23E, 0x16578216,
|
286 |
-
0x95106395, 0x5BEF015B, 0x4DB8834D, 0x91862E91, 0xB56DD9B5, 0x1F83511F, 0x53AA9B53, 0x635D7C63,
|
287 |
-
0x3B68A63B, 0x3FFEEB3F, 0xD630A5D6, 0x257ABE25, 0xA7AC16A7, 0x0F090C0F, 0x35F0E335, 0x23A76123,
|
288 |
-
0xF090C0F0, 0xAFE98CAF, 0x809D3A80, 0x925CF592, 0x810C7381, 0x27312C27, 0x76D02576, 0xE7560BE7,
|
289 |
-
0x7B92BB7B, 0xE9CE4EE9, 0xF10189F1, 0x9F1E6B9F, 0xA93453A9, 0xC4F16AC4, 0x99C3B499, 0x975BF197,
|
290 |
-
0x8347E183, 0x6B18E66B, 0xC822BDC8, 0x0E98450E, 0x6E1FE26E, 0xC9B3F4C9, 0x2F74B62F, 0xCBF866CB,
|
291 |
-
0xFF99CCFF, 0xEA1495EA, 0xED5803ED, 0xF7DC56F7, 0xE18BD4E1, 0x1B151C1B, 0xADA21EAD, 0x0CD3D70C,
|
292 |
-
0x2BE2FB2B, 0x1DC8C31D, 0x195E8E19, 0xC22CB5C2, 0x8949E989, 0x12C1CF12, 0x7E95BF7E, 0x207DBA20,
|
293 |
-
0x6411EA64, 0x840B7784, 0x6DC5396D, 0x6A89AF6A, 0xD17C33D1, 0xA171C9A1, 0xCEFF62CE, 0x37BB7137,
|
294 |
-
0xFB0F81FB, 0x3DB5793D, 0x51E10951, 0xDC3EADDC, 0x2D3F242D, 0xA476CDA4, 0x9D55F99D, 0xEE82D8EE,
|
295 |
-
0x8640E586, 0xAE78C5AE, 0xCD25B9CD, 0x04964D04, 0x55774455, 0x0A0E080A, 0x13508613, 0x30F7E730,
|
296 |
-
0xD337A1D3, 0x40FA1D40, 0x3461AA34, 0x8C4EED8C, 0xB3B006B3, 0x6C54706C, 0x2A73B22A, 0x523BD252,
|
297 |
-
0x0B9F410B, 0x8B027B8B, 0x88D8A088, 0x4FF3114F, 0x67CB3167, 0x4627C246, 0xC06727C0, 0xB4FC90B4,
|
298 |
-
0x28382028, 0x7F04F67F, 0x78486078, 0x2EE5FF2E, 0x074C9607, 0x4B655C4B, 0xC72BB1C7, 0x6F8EAB6F,
|
299 |
-
0x0D429E0D, 0xBBF59CBB, 0xF2DB52F2, 0xF34A1BF3, 0xA63D5FA6, 0x59A49359, 0xBCB90ABC, 0x3AF9EF3A,
|
300 |
-
0xEF1391EF, 0xFE0885FE, 0x01914901, 0x6116EE61, 0x7CDE2D7C, 0xB2214FB2, 0x42B18F42, 0xDB723BDB,
|
301 |
-
0xB82F47B8, 0x48BF8748, 0x2CAE6D2C, 0xE3C046E3, 0x573CD657, 0x859A3E85, 0x29A96929, 0x7D4F647D,
|
302 |
-
0x94812A94, 0x492ECE49, 0x17C6CB17, 0xCA692FCA, 0xC3BDFCC3, 0x5CA3975C, 0x5EE8055E, 0xD0ED7AD0,
|
303 |
-
0x87D1AC87, 0x8E057F8E, 0xBA64D5BA, 0xA8A51AA8, 0xB7264BB7, 0xB9BE0EB9, 0x6087A760, 0xF8D55AF8,
|
304 |
-
0x22362822, 0x111B1411, 0xDE753FDE, 0x79D92979, 0xAAEE88AA, 0x332D3C33, 0x5F794C5F, 0xB6B702B6,
|
305 |
-
0x96CAB896, 0x5835DA58, 0x9CC4B09C, 0xFC4317FC, 0x1A84551A, 0xF64D1FF6, 0x1C598A1C, 0x38B27D38,
|
306 |
-
0xAC3357AC, 0x18CFC718, 0xF4068DF4, 0x69537469, 0x749BB774, 0xF597C4F5, 0x56AD9F56, 0xDAE372DA,
|
307 |
-
0xD5EA7ED5, 0x4AF4154A, 0x9E8F229E, 0xA2AB12A2, 0x4E62584E, 0xE85F07E8, 0xE51D99E5, 0x39233439,
|
308 |
-
0xC1F66EC1, 0x446C5044, 0x5D32DE5D, 0x72466872, 0x26A06526, 0x93CDBC93, 0x03DADB03, 0xC6BAF8C6,
|
309 |
-
0xFA9EC8FA, 0x82D6A882, 0xCF6E2BCF, 0x50704050, 0xEB85DCEB, 0x750AFE75, 0x8A93328A, 0x8DDFA48D,
|
310 |
-
0x4C29CA4C, 0x141C1014, 0x73D72173, 0xCCB4F0CC, 0x09D4D309, 0x108A5D10, 0xE2510FE2, 0x00000000,
|
311 |
-
0x9A196F9A, 0xE01A9DE0, 0x8F94368F, 0xE6C742E6, 0xECC94AEC, 0xFDD25EFD, 0xAB7FC1AB, 0xD8A8E0D8
|
312 |
-
);
|
313 |
-
|
314 |
-
/**
|
315 |
-
* The Key Schedule Array
|
316 |
-
*
|
317 |
-
* @var array
|
318 |
-
* @access private
|
319 |
-
*/
|
320 |
-
var $K = array();
|
321 |
-
|
322 |
-
/**
|
323 |
-
* The Key depended S-Table 0
|
324 |
-
*
|
325 |
-
* @var array
|
326 |
-
* @access private
|
327 |
-
*/
|
328 |
-
var $S0 = array();
|
329 |
-
|
330 |
-
/**
|
331 |
-
* The Key depended S-Table 1
|
332 |
-
*
|
333 |
-
* @var array
|
334 |
-
* @access private
|
335 |
-
*/
|
336 |
-
var $S1 = array();
|
337 |
-
|
338 |
-
/**
|
339 |
-
* The Key depended S-Table 2
|
340 |
-
*
|
341 |
-
* @var array
|
342 |
-
* @access private
|
343 |
-
*/
|
344 |
-
var $S2 = array();
|
345 |
-
|
346 |
-
/**
|
347 |
-
* The Key depended S-Table 3
|
348 |
-
*
|
349 |
-
* @var array
|
350 |
-
* @access private
|
351 |
-
*/
|
352 |
-
var $S3 = array();
|
353 |
-
|
354 |
-
/**
|
355 |
-
* Holds the last used key
|
356 |
-
*
|
357 |
-
* @var array
|
358 |
-
* @access private
|
359 |
-
*/
|
360 |
-
var $kl;
|
361 |
-
|
362 |
-
/**
|
363 |
-
* The Key Length (in bytes)
|
364 |
-
*
|
365 |
-
* @see Crypt_Twofish::setKeyLength()
|
366 |
-
* @var int
|
367 |
-
* @access private
|
368 |
-
*/
|
369 |
-
var $key_length = 16;
|
370 |
-
|
371 |
-
/**
|
372 |
-
* Sets the key length.
|
373 |
-
*
|
374 |
-
* Valid key lengths are 128, 192 or 256 bits
|
375 |
-
*
|
376 |
-
* @access public
|
377 |
-
* @param int $length
|
378 |
-
*/
|
379 |
-
function setKeyLength($length)
|
380 |
-
{
|
381 |
-
switch (true) {
|
382 |
-
case $length <= 128:
|
383 |
-
$this->key_length = 16;
|
384 |
-
break;
|
385 |
-
case $length <= 192:
|
386 |
-
$this->key_length = 24;
|
387 |
-
break;
|
388 |
-
default:
|
389 |
-
$this->key_length = 32;
|
390 |
-
}
|
391 |
-
|
392 |
-
parent::setKeyLength($length);
|
393 |
-
}
|
394 |
-
|
395 |
-
/**
|
396 |
-
* Setup the key (expansion)
|
397 |
-
*
|
398 |
-
* @see \phpseclib\Crypt\Base::_setupKey()
|
399 |
-
* @access private
|
400 |
-
*/
|
401 |
-
function _setupKey()
|
402 |
-
{
|
403 |
-
if (isset($this->kl['key']) && $this->key === $this->kl['key']) {
|
404 |
-
// already expanded
|
405 |
-
return;
|
406 |
-
}
|
407 |
-
$this->kl = array('key' => $this->key);
|
408 |
-
|
409 |
-
/* Key expanding and generating the key-depended s-boxes */
|
410 |
-
$le_longs = unpack('V*', $this->key);
|
411 |
-
$key = unpack('C*', $this->key);
|
412 |
-
$m0 = $this->m0;
|
413 |
-
$m1 = $this->m1;
|
414 |
-
$m2 = $this->m2;
|
415 |
-
$m3 = $this->m3;
|
416 |
-
$q0 = $this->q0;
|
417 |
-
$q1 = $this->q1;
|
418 |
-
|
419 |
-
$K = $S0 = $S1 = $S2 = $S3 = array();
|
420 |
-
|
421 |
-
switch (strlen($this->key)) {
|
422 |
-
case 16:
|
423 |
-
list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[1], $le_longs[2]);
|
424 |
-
list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[3], $le_longs[4]);
|
425 |
-
for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
|
426 |
-
$A = $m0[$q0[$q0[$i] ^ $key[ 9]] ^ $key[1]] ^
|
427 |
-
$m1[$q0[$q1[$i] ^ $key[10]] ^ $key[2]] ^
|
428 |
-
$m2[$q1[$q0[$i] ^ $key[11]] ^ $key[3]] ^
|
429 |
-
$m3[$q1[$q1[$i] ^ $key[12]] ^ $key[4]];
|
430 |
-
$B = $m0[$q0[$q0[$j] ^ $key[13]] ^ $key[5]] ^
|
431 |
-
$m1[$q0[$q1[$j] ^ $key[14]] ^ $key[6]] ^
|
432 |
-
$m2[$q1[$q0[$j] ^ $key[15]] ^ $key[7]] ^
|
433 |
-
$m3[$q1[$q1[$j] ^ $key[16]] ^ $key[8]];
|
434 |
-
$B = ($B << 8) | ($B >> 24 & 0xff);
|
435 |
-
$K[] = $A+= $B;
|
436 |
-
$K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
|
437 |
-
}
|
438 |
-
for ($i = 0; $i < 256; ++$i) {
|
439 |
-
$S0[$i] = $m0[$q0[$q0[$i] ^ $s4] ^ $s0];
|
440 |
-
$S1[$i] = $m1[$q0[$q1[$i] ^ $s5] ^ $s1];
|
441 |
-
$S2[$i] = $m2[$q1[$q0[$i] ^ $s6] ^ $s2];
|
442 |
-
$S3[$i] = $m3[$q1[$q1[$i] ^ $s7] ^ $s3];
|
443 |
-
}
|
444 |
-
break;
|
445 |
-
case 24:
|
446 |
-
list($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[1], $le_longs[2]);
|
447 |
-
list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[3], $le_longs[4]);
|
448 |
-
list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[5], $le_longs[6]);
|
449 |
-
for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
|
450 |
-
$A = $m0[$q0[$q0[$q1[$i] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^
|
451 |
-
$m1[$q0[$q1[$q1[$i] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
|
452 |
-
$m2[$q1[$q0[$q0[$i] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^
|
453 |
-
$m3[$q1[$q1[$q0[$i] ^ $key[20]] ^ $key[12]] ^ $key[4]];
|
454 |
-
$B = $m0[$q0[$q0[$q1[$j] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^
|
455 |
-
$m1[$q0[$q1[$q1[$j] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^
|
456 |
-
$m2[$q1[$q0[$q0[$j] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^
|
457 |
-
$m3[$q1[$q1[$q0[$j] ^ $key[24]] ^ $key[16]] ^ $key[8]];
|
458 |
-
$B = ($B << 8) | ($B >> 24 & 0xff);
|
459 |
-
$K[] = $A+= $B;
|
460 |
-
$K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
|
461 |
-
}
|
462 |
-
for ($i = 0; $i < 256; ++$i) {
|
463 |
-
$S0[$i] = $m0[$q0[$q0[$q1[$i] ^ $s8] ^ $s4] ^ $s0];
|
464 |
-
$S1[$i] = $m1[$q0[$q1[$q1[$i] ^ $s9] ^ $s5] ^ $s1];
|
465 |
-
$S2[$i] = $m2[$q1[$q0[$q0[$i] ^ $sa] ^ $s6] ^ $s2];
|
466 |
-
$S3[$i] = $m3[$q1[$q1[$q0[$i] ^ $sb] ^ $s7] ^ $s3];
|
467 |
-
}
|
468 |
-
break;
|
469 |
-
default: // 32
|
470 |
-
list($sf, $se, $sd, $sc) = $this->_mdsrem($le_longs[1], $le_longs[2]);
|
471 |
-
list($sb, $sa, $s9, $s8) = $this->_mdsrem($le_longs[3], $le_longs[4]);
|
472 |
-
list($s7, $s6, $s5, $s4) = $this->_mdsrem($le_longs[5], $le_longs[6]);
|
473 |
-
list($s3, $s2, $s1, $s0) = $this->_mdsrem($le_longs[7], $le_longs[8]);
|
474 |
-
for ($i = 0, $j = 1; $i < 40; $i+= 2, $j+= 2) {
|
475 |
-
$A = $m0[$q0[$q0[$q1[$q1[$i] ^ $key[25]] ^ $key[17]] ^ $key[ 9]] ^ $key[1]] ^
|
476 |
-
$m1[$q0[$q1[$q1[$q0[$i] ^ $key[26]] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^
|
477 |
-
$m2[$q1[$q0[$q0[$q0[$i] ^ $key[27]] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^
|
478 |
-
$m3[$q1[$q1[$q0[$q1[$i] ^ $key[28]] ^ $key[20]] ^ $key[12]] ^ $key[4]];
|
479 |
-
$B = $m0[$q0[$q0[$q1[$q1[$j] ^ $key[29]] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^
|
480 |
-
$m1[$q0[$q1[$q1[$q0[$j] ^ $key[30]] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^
|
481 |
-
$m2[$q1[$q0[$q0[$q0[$j] ^ $key[31]] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^
|
482 |
-
$m3[$q1[$q1[$q0[$q1[$j] ^ $key[32]] ^ $key[24]] ^ $key[16]] ^ $key[8]];
|
483 |
-
$B = ($B << 8) | ($B >> 24 & 0xff);
|
484 |
-
$K[] = $A+= $B;
|
485 |
-
$K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
|
486 |
-
}
|
487 |
-
for ($i = 0; $i < 256; ++$i) {
|
488 |
-
$S0[$i] = $m0[$q0[$q0[$q1[$q1[$i] ^ $sc] ^ $s8] ^ $s4] ^ $s0];
|
489 |
-
$S1[$i] = $m1[$q0[$q1[$q1[$q0[$i] ^ $sd] ^ $s9] ^ $s5] ^ $s1];
|
490 |
-
$S2[$i] = $m2[$q1[$q0[$q0[$q0[$i] ^ $se] ^ $sa] ^ $s6] ^ $s2];
|
491 |
-
$S3[$i] = $m3[$q1[$q1[$q0[$q1[$i] ^ $sf] ^ $sb] ^ $s7] ^ $s3];
|
492 |
-
}
|
493 |
-
}
|
494 |
-
|
495 |
-
$this->K = $K;
|
496 |
-
$this->S0 = $S0;
|
497 |
-
$this->S1 = $S1;
|
498 |
-
$this->S2 = $S2;
|
499 |
-
$this->S3 = $S3;
|
500 |
-
}
|
501 |
-
|
502 |
-
/**
|
503 |
-
* _mdsrem function using by the twofish cipher algorithm
|
504 |
-
*
|
505 |
-
* @access private
|
506 |
-
* @param string $A
|
507 |
-
* @param string $B
|
508 |
-
* @return array
|
509 |
-
*/
|
510 |
-
function _mdsrem($A, $B)
|
511 |
-
{
|
512 |
-
// No gain by unrolling this loop.
|
513 |
-
for ($i = 0; $i < 8; ++$i) {
|
514 |
-
// Get most significant coefficient.
|
515 |
-
$t = 0xff & ($B >> 24);
|
516 |
-
|
517 |
-
// Shift the others up.
|
518 |
-
$B = ($B << 8) | (0xff & ($A >> 24));
|
519 |
-
$A<<= 8;
|
520 |
-
|
521 |
-
$u = $t << 1;
|
522 |
-
|
523 |
-
// Subtract the modular polynomial on overflow.
|
524 |
-
if ($t & 0x80) {
|
525 |
-
$u^= 0x14d;
|
526 |
-
}
|
527 |
-
|
528 |
-
// Remove t * (a * x^2 + 1).
|
529 |
-
$B ^= $t ^ ($u << 16);
|
530 |
-
|
531 |
-
// Form u = a*t + t/a = t*(a + 1/a).
|
532 |
-
$u^= 0x7fffffff & ($t >> 1);
|
533 |
-
|
534 |
-
// Add the modular polynomial on underflow.
|
535 |
-
if ($t & 0x01) {
|
536 |
-
$u^= 0xa6 ;
|
537 |
-
}
|
538 |
-
|
539 |
-
// Remove t * (a + 1/a) * (x^3 + x).
|
540 |
-
$B^= ($u << 24) | ($u << 8);
|
541 |
-
}
|
542 |
-
|
543 |
-
return array(
|
544 |
-
0xff & $B >> 24,
|
545 |
-
0xff & $B >> 16,
|
546 |
-
0xff & $B >> 8,
|
547 |
-
0xff & $B);
|
548 |
-
}
|
549 |
-
|
550 |
-
/**
|
551 |
-
* Encrypts a block
|
552 |
-
*
|
553 |
-
* @access private
|
554 |
-
* @param string $in
|
555 |
-
* @return string
|
556 |
-
*/
|
557 |
-
function _encryptBlock($in)
|
558 |
-
{
|
559 |
-
$S0 = $this->S0;
|
560 |
-
$S1 = $this->S1;
|
561 |
-
$S2 = $this->S2;
|
562 |
-
$S3 = $this->S3;
|
563 |
-
$K = $this->K;
|
564 |
-
|
565 |
-
$in = unpack("V4", $in);
|
566 |
-
$R0 = $K[0] ^ $in[1];
|
567 |
-
$R1 = $K[1] ^ $in[2];
|
568 |
-
$R2 = $K[2] ^ $in[3];
|
569 |
-
$R3 = $K[3] ^ $in[4];
|
570 |
-
|
571 |
-
$ki = 7;
|
572 |
-
while ($ki < 39) {
|
573 |
-
$t0 = $S0[ $R0 & 0xff] ^
|
574 |
-
$S1[($R0 >> 8) & 0xff] ^
|
575 |
-
$S2[($R0 >> 16) & 0xff] ^
|
576 |
-
$S3[($R0 >> 24) & 0xff];
|
577 |
-
$t1 = $S0[($R1 >> 24) & 0xff] ^
|
578 |
-
$S1[ $R1 & 0xff] ^
|
579 |
-
$S2[($R1 >> 8) & 0xff] ^
|
580 |
-
$S3[($R1 >> 16) & 0xff];
|
581 |
-
$R2^= $t0 + $t1 + $K[++$ki];
|
582 |
-
$R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
|
583 |
-
$R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]);
|
584 |
-
|
585 |
-
$t0 = $S0[ $R2 & 0xff] ^
|
586 |
-
$S1[($R2 >> 8) & 0xff] ^
|
587 |
-
$S2[($R2 >> 16) & 0xff] ^
|
588 |
-
$S3[($R2 >> 24) & 0xff];
|
589 |
-
$t1 = $S0[($R3 >> 24) & 0xff] ^
|
590 |
-
$S1[ $R3 & 0xff] ^
|
591 |
-
$S2[($R3 >> 8) & 0xff] ^
|
592 |
-
$S3[($R3 >> 16) & 0xff];
|
593 |
-
$R0^= ($t0 + $t1 + $K[++$ki]);
|
594 |
-
$R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
|
595 |
-
$R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]);
|
596 |
-
}
|
597 |
-
|
598 |
-
// @codingStandardsIgnoreStart
|
599 |
-
return pack("V4", $K[4] ^ $R2,
|
600 |
-
$K[5] ^ $R3,
|
601 |
-
$K[6] ^ $R0,
|
602 |
-
$K[7] ^ $R1);
|
603 |
-
// @codingStandardsIgnoreEnd
|
604 |
-
}
|
605 |
-
|
606 |
-
/**
|
607 |
-
* Decrypts a block
|
608 |
-
*
|
609 |
-
* @access private
|
610 |
-
* @param string $in
|
611 |
-
* @return string
|
612 |
-
*/
|
613 |
-
function _decryptBlock($in)
|
614 |
-
{
|
615 |
-
$S0 = $this->S0;
|
616 |
-
$S1 = $this->S1;
|
617 |
-
$S2 = $this->S2;
|
618 |
-
$S3 = $this->S3;
|
619 |
-
$K = $this->K;
|
620 |
-
|
621 |
-
$in = unpack("V4", $in);
|
622 |
-
$R0 = $K[4] ^ $in[1];
|
623 |
-
$R1 = $K[5] ^ $in[2];
|
624 |
-
$R2 = $K[6] ^ $in[3];
|
625 |
-
$R3 = $K[7] ^ $in[4];
|
626 |
-
|
627 |
-
$ki = 40;
|
628 |
-
while ($ki > 8) {
|
629 |
-
$t0 = $S0[$R0 & 0xff] ^
|
630 |
-
$S1[$R0 >> 8 & 0xff] ^
|
631 |
-
$S2[$R0 >> 16 & 0xff] ^
|
632 |
-
$S3[$R0 >> 24 & 0xff];
|
633 |
-
$t1 = $S0[$R1 >> 24 & 0xff] ^
|
634 |
-
$S1[$R1 & 0xff] ^
|
635 |
-
$S2[$R1 >> 8 & 0xff] ^
|
636 |
-
$S3[$R1 >> 16 & 0xff];
|
637 |
-
$R3^= $t0 + ($t1 << 1) + $K[--$ki];
|
638 |
-
$R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
|
639 |
-
$R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ($t0 + $t1 + $K[--$ki]);
|
640 |
-
|
641 |
-
$t0 = $S0[$R2 & 0xff] ^
|
642 |
-
$S1[$R2 >> 8 & 0xff] ^
|
643 |
-
$S2[$R2 >> 16 & 0xff] ^
|
644 |
-
$S3[$R2 >> 24 & 0xff];
|
645 |
-
$t1 = $S0[$R3 >> 24 & 0xff] ^
|
646 |
-
$S1[$R3 & 0xff] ^
|
647 |
-
$S2[$R3 >> 8 & 0xff] ^
|
648 |
-
$S3[$R3 >> 16 & 0xff];
|
649 |
-
$R1^= $t0 + ($t1 << 1) + $K[--$ki];
|
650 |
-
$R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
|
651 |
-
$R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + $K[--$ki]);
|
652 |
-
}
|
653 |
-
|
654 |
-
// @codingStandardsIgnoreStart
|
655 |
-
return pack("V4", $K[0] ^ $R2,
|
656 |
-
$K[1] ^ $R3,
|
657 |
-
$K[2] ^ $R0,
|
658 |
-
$K[3] ^ $R1);
|
659 |
-
// @codingStandardsIgnoreEnd
|
660 |
-
}
|
661 |
-
|
662 |
-
/**
|
663 |
-
* Setup the performance-optimized function for de/encrypt()
|
664 |
-
*
|
665 |
-
* @see \phpseclib\Crypt\Base::_setupInlineCrypt()
|
666 |
-
* @access private
|
667 |
-
*/
|
668 |
-
function _setupInlineCrypt()
|
669 |
-
{
|
670 |
-
$lambda_functions =& self::_getLambdaFunctions();
|
671 |
-
|
672 |
-
// Max. 10 Ultra-Hi-optimized inline-crypt functions. After that, we'll (still) create very fast code, but not the ultimate fast one.
|
673 |
-
// (Currently, for Crypt_Twofish, one generated $lambda_function cost on php5.5@32bit ~140kb unfreeable mem and ~240kb on php5.5@64bit)
|
674 |
-
$gen_hi_opt_code = (bool)(count($lambda_functions) < 10);
|
675 |
-
|
676 |
-
// Generation of a unique hash for our generated code
|
677 |
-
$code_hash = "Crypt_Twofish, {$this->mode}";
|
678 |
-
if ($gen_hi_opt_code) {
|
679 |
-
$code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
|
680 |
-
}
|
681 |
-
|
682 |
-
if (!isset($lambda_functions[$code_hash])) {
|
683 |
-
switch (true) {
|
684 |
-
case $gen_hi_opt_code:
|
685 |
-
$K = $this->K;
|
686 |
-
$init_crypt = '
|
687 |
-
static $S0, $S1, $S2, $S3;
|
688 |
-
if (!$S0) {
|
689 |
-
for ($i = 0; $i < 256; ++$i) {
|
690 |
-
$S0[] = (int)$self->S0[$i];
|
691 |
-
$S1[] = (int)$self->S1[$i];
|
692 |
-
$S2[] = (int)$self->S2[$i];
|
693 |
-
$S3[] = (int)$self->S3[$i];
|
694 |
-
}
|
695 |
-
}
|
696 |
-
';
|
697 |
-
break;
|
698 |
-
default:
|
699 |
-
$K = array();
|
700 |
-
for ($i = 0; $i < 40; ++$i) {
|
701 |
-
$K[] = '$K_' . $i;
|
702 |
-
}
|
703 |
-
$init_crypt = '
|
704 |
-
$S0 = $self->S0;
|
705 |
-
$S1 = $self->S1;
|
706 |
-
$S2 = $self->S2;
|
707 |
-
$S3 = $self->S3;
|
708 |
-
list(' . implode(',', $K) . ') = $self->K;
|
709 |
-
';
|
710 |
-
}
|
711 |
-
|
712 |
-
// Generating encrypt code:
|
713 |
-
$encrypt_block = '
|
714 |
-
$in = unpack("V4", $in);
|
715 |
-
$R0 = '.$K[0].' ^ $in[1];
|
716 |
-
$R1 = '.$K[1].' ^ $in[2];
|
717 |
-
$R2 = '.$K[2].' ^ $in[3];
|
718 |
-
$R3 = '.$K[3].' ^ $in[4];
|
719 |
-
';
|
720 |
-
for ($ki = 7, $i = 0; $i < 8; ++$i) {
|
721 |
-
$encrypt_block.= '
|
722 |
-
$t0 = $S0[ $R0 & 0xff] ^
|
723 |
-
$S1[($R0 >> 8) & 0xff] ^
|
724 |
-
$S2[($R0 >> 16) & 0xff] ^
|
725 |
-
$S3[($R0 >> 24) & 0xff];
|
726 |
-
$t1 = $S0[($R1 >> 24) & 0xff] ^
|
727 |
-
$S1[ $R1 & 0xff] ^
|
728 |
-
$S2[($R1 >> 8) & 0xff] ^
|
729 |
-
$S3[($R1 >> 16) & 0xff];
|
730 |
-
$R2^= ($t0 + $t1 + '.$K[++$ki].');
|
731 |
-
$R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
|
732 |
-
$R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ($t0 + ($t1 << 1) + '.$K[++$ki].');
|
733 |
-
|
734 |
-
$t0 = $S0[ $R2 & 0xff] ^
|
735 |
-
$S1[($R2 >> 8) & 0xff] ^
|
736 |
-
$S2[($R2 >> 16) & 0xff] ^
|
737 |
-
$S3[($R2 >> 24) & 0xff];
|
738 |
-
$t1 = $S0[($R3 >> 24) & 0xff] ^
|
739 |
-
$S1[ $R3 & 0xff] ^
|
740 |
-
$S2[($R3 >> 8) & 0xff] ^
|
741 |
-
$S3[($R3 >> 16) & 0xff];
|
742 |
-
$R0^= ($t0 + $t1 + '.$K[++$ki].');
|
743 |
-
$R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
|
744 |
-
$R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + '.$K[++$ki].');
|
745 |
-
';
|
746 |
-
}
|
747 |
-
$encrypt_block.= '
|
748 |
-
$in = pack("V4", '.$K[4].' ^ $R2,
|
749 |
-
'.$K[5].' ^ $R3,
|
750 |
-
'.$K[6].' ^ $R0,
|
751 |
-
'.$K[7].' ^ $R1);
|
752 |
-
';
|
753 |
-
|
754 |
-
// Generating decrypt code:
|
755 |
-
$decrypt_block = '
|
756 |
-
$in = unpack("V4", $in);
|
757 |
-
$R0 = '.$K[4].' ^ $in[1];
|
758 |
-
$R1 = '.$K[5].' ^ $in[2];
|
759 |
-
$R2 = '.$K[6].' ^ $in[3];
|
760 |
-
$R3 = '.$K[7].' ^ $in[4];
|
761 |
-
';
|
762 |
-
for ($ki = 40, $i = 0; $i < 8; ++$i) {
|
763 |
-
$decrypt_block.= '
|
764 |
-
$t0 = $S0[$R0 & 0xff] ^
|
765 |
-
$S1[$R0 >> 8 & 0xff] ^
|
766 |
-
$S2[$R0 >> 16 & 0xff] ^
|
767 |
-
$S3[$R0 >> 24 & 0xff];
|
768 |
-
$t1 = $S0[$R1 >> 24 & 0xff] ^
|
769 |
-
$S1[$R1 & 0xff] ^
|
770 |
-
$S2[$R1 >> 8 & 0xff] ^
|
771 |
-
$S3[$R1 >> 16 & 0xff];
|
772 |
-
$R3^= $t0 + ($t1 << 1) + '.$K[--$ki].';
|
773 |
-
$R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
|
774 |
-
$R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ($t0 + $t1 + '.$K[--$ki].');
|
775 |
-
|
776 |
-
$t0 = $S0[$R2 & 0xff] ^
|
777 |
-
$S1[$R2 >> 8 & 0xff] ^
|
778 |
-
$S2[$R2 >> 16 & 0xff] ^
|
779 |
-
$S3[$R2 >> 24 & 0xff];
|
780 |
-
$t1 = $S0[$R3 >> 24 & 0xff] ^
|
781 |
-
$S1[$R3 & 0xff] ^
|
782 |
-
$S2[$R3 >> 8 & 0xff] ^
|
783 |
-
$S3[$R3 >> 16 & 0xff];
|
784 |
-
$R1^= $t0 + ($t1 << 1) + '.$K[--$ki].';
|
785 |
-
$R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
|
786 |
-
$R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + '.$K[--$ki].');
|
787 |
-
';
|
788 |
-
}
|
789 |
-
$decrypt_block.= '
|
790 |
-
$in = pack("V4", '.$K[0].' ^ $R2,
|
791 |
-
'.$K[1].' ^ $R3,
|
792 |
-
'.$K[2].' ^ $R0,
|
793 |
-
'.$K[3].' ^ $R1);
|
794 |
-
';
|
795 |
-
|
796 |
-
$lambda_functions[$code_hash] = $this->_createInlineCryptFunction(
|
797 |
-
array(
|
798 |
-
'init_crypt' => $init_crypt,
|
799 |
-
'init_encrypt' => '',
|
800 |
-
'init_decrypt' => '',
|
801 |
-
'encrypt_block' => $encrypt_block,
|
802 |
-
'decrypt_block' => $decrypt_block
|
803 |
-
)
|
804 |
-
);
|
805 |
-
}
|
806 |
-
$this->inline_crypt = $lambda_functions[$code_hash];
|
807 |
-
}
|
808 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/phpseclib/phpseclib/phpseclib/File/ANSI.php
DELETED
@@ -1,577 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Pure-PHP ANSI Decoder
|
5 |
-
*
|
6 |
-
* PHP version 5
|
7 |
-
*
|
8 |
-
* If you call read() in \phpseclib\Net\SSH2 you may get {@link http://en.wikipedia.org/wiki/ANSI_escape_code ANSI escape codes} back.
|
9 |
-
* They'd look like chr(0x1B) . '[00m' or whatever (0x1B = ESC). They tell a
|
10 |
-
* {@link http://en.wikipedia.org/wiki/Terminal_emulator terminal emulator} how to format the characters, what
|
11 |
-
* color to display them in, etc. \phpseclib\File\ANSI is a {@link http://en.wikipedia.org/wiki/VT100 VT100} terminal emulator.
|
12 |
-
*
|
13 |
-
* @category File
|
14 |
-
* @package ANSI
|
15 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
16 |
-
* @copyright 2012 Jim Wigginton
|
17 |
-
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
18 |
-
* @link http://phpseclib.sourceforge.net
|
19 |
-
*/
|
20 |
-
|
21 |
-
namespace phpseclib\File;
|
22 |
-
|
23 |
-
/**
|
24 |
-
* Pure-PHP ANSI Decoder
|
25 |
-
*
|
26 |
-
* @package ANSI
|
27 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
28 |
-
* @access public
|
29 |
-
*/
|
30 |
-
class ANSI
|
31 |
-
{
|
32 |
-
/**
|
33 |
-
* Max Width
|
34 |
-
*
|
35 |
-
* @var int
|
36 |
-
* @access private
|
37 |
-
*/
|
38 |
-
var $max_x;
|
39 |
-
|
40 |
-
/**
|
41 |
-
* Max Height
|
42 |
-
*
|
43 |
-
* @var int
|
44 |
-
* @access private
|
45 |
-
*/
|
46 |
-
var $max_y;
|
47 |
-
|
48 |
-
/**
|
49 |
-
* Max History
|
50 |
-
*
|
51 |
-
* @var int
|
52 |
-
* @access private
|
53 |
-
*/
|
54 |
-
var $max_history;
|
55 |
-
|
56 |
-
/**
|
57 |
-
* History
|
58 |
-
*
|
59 |
-
* @var array
|
60 |
-
* @access private
|
61 |
-
*/
|
62 |
-
var $history;
|
63 |
-
|
64 |
-
/**
|
65 |
-
* History Attributes
|
66 |
-
*
|
67 |
-
* @var array
|
68 |
-
* @access private
|
69 |
-
*/
|
70 |
-
var $history_attrs;
|
71 |
-
|
72 |
-
/**
|
73 |
-
* Current Column
|
74 |
-
*
|
75 |
-
* @var int
|
76 |
-
* @access private
|
77 |
-
*/
|
78 |
-
var $x;
|
79 |
-
|
80 |
-
/**
|
81 |
-
* Current Row
|
82 |
-
*
|
83 |
-
* @var int
|
84 |
-
* @access private
|
85 |
-
*/
|
86 |
-
var $y;
|
87 |
-
|
88 |
-
/**
|
89 |
-
* Old Column
|
90 |
-
*
|
91 |
-
* @var int
|
92 |
-
* @access private
|
93 |
-
*/
|
94 |
-
var $old_x;
|
95 |
-
|
96 |
-
/**
|
97 |
-
* Old Row
|
98 |
-
*
|
99 |
-
* @var int
|
100 |
-
* @access private
|
101 |
-
*/
|
102 |
-
var $old_y;
|
103 |
-
|
104 |
-
/**
|
105 |
-
* An empty attribute cell
|
106 |
-
*
|
107 |
-
* @var object
|
108 |
-
* @access private
|
109 |
-
*/
|
110 |
-
var $base_attr_cell;
|
111 |
-
|
112 |
-
/**
|
113 |
-
* The current attribute cell
|
114 |
-
*
|
115 |
-
* @var object
|
116 |
-
* @access private
|
117 |
-
*/
|
118 |
-
var $attr_cell;
|
119 |
-
|
120 |
-
/**
|
121 |
-
* An empty attribute row
|
122 |
-
*
|
123 |
-
* @var array
|
124 |
-
* @access private
|
125 |
-
*/
|
126 |
-
var $attr_row;
|
127 |
-
|
128 |
-
/**
|
129 |
-
* The current screen text
|
130 |
-
*
|
131 |
-
* @var array
|
132 |
-
* @access private
|
133 |
-
*/
|
134 |
-
var $screen;
|
135 |
-
|
136 |
-
/**
|
137 |
-
* The current screen attributes
|
138 |
-
*
|
139 |
-
* @var array
|
140 |
-
* @access private
|
141 |
-
*/
|
142 |
-
var $attrs;
|
143 |
-
|
144 |
-
/**
|
145 |
-
* Current ANSI code
|
146 |
-
*
|
147 |
-
* @var string
|
148 |
-
* @access private
|
149 |
-
*/
|
150 |
-
var $ansi;
|
151 |
-
|
152 |
-
/**
|
153 |
-
* Tokenization
|
154 |
-
*
|
155 |
-
* @var array
|
156 |
-
* @access private
|
157 |
-
*/
|
158 |
-
var $tokenization;
|
159 |
-
|
160 |
-
/**
|
161 |
-
* Default Constructor.
|
162 |
-
*
|
163 |
-
* @return \phpseclib\File\ANSI
|
164 |
-
* @access public
|
165 |
-
*/
|
166 |
-
function __construct()
|
167 |
-
{
|
168 |
-
$attr_cell = new \stdClass();
|
169 |
-
$attr_cell->bold = false;
|
170 |
-
$attr_cell->underline = false;
|
171 |
-
$attr_cell->blink = false;
|
172 |
-
$attr_cell->background = 'black';
|
173 |
-
$attr_cell->foreground = 'white';
|
174 |
-
$attr_cell->reverse = false;
|
175 |
-
$this->base_attr_cell = clone $attr_cell;
|
176 |
-
$this->attr_cell = clone $attr_cell;
|
177 |
-
|
178 |
-
$this->setHistory(200);
|
179 |
-
$this->setDimensions(80, 24);
|
180 |
-
}
|
181 |
-
|
182 |
-
/**
|
183 |
-
* Set terminal width and height
|
184 |
-
*
|
185 |
-
* Resets the screen as well
|
186 |
-
*
|
187 |
-
* @param int $x
|
188 |
-
* @param int $y
|
189 |
-
* @access public
|
190 |
-
*/
|
191 |
-
function setDimensions($x, $y)
|
192 |
-
{
|
193 |
-
$this->max_x = $x - 1;
|
194 |
-
$this->max_y = $y - 1;
|
195 |
-
$this->x = $this->y = 0;
|
196 |
-
$this->history = $this->history_attrs = array();
|
197 |
-
$this->attr_row = array_fill(0, $this->max_x + 2, $this->base_attr_cell);
|
198 |
-
$this->screen = array_fill(0, $this->max_y + 1, '');
|
199 |
-
$this->attrs = array_fill(0, $this->max_y + 1, $this->attr_row);
|
200 |
-
$this->ansi = '';
|
201 |
-
}
|
202 |
-
|
203 |
-
/**
|
204 |
-
* Set the number of lines that should be logged past the terminal height
|
205 |
-
*
|
206 |
-
* @param int $x
|
207 |
-
* @param int $y
|
208 |
-
* @access public
|
209 |
-
*/
|
210 |
-
function setHistory($history)
|
211 |
-
{
|
212 |
-
$this->max_history = $history;
|
213 |
-
}
|
214 |
-
|
215 |
-
/**
|
216 |
-
* Load a string
|
217 |
-
*
|
218 |
-
* @param string $source
|
219 |
-
* @access public
|
220 |
-
*/
|
221 |
-
function loadString($source)
|
222 |
-
{
|
223 |
-
$this->setDimensions($this->max_x + 1, $this->max_y + 1);
|
224 |
-
$this->appendString($source);
|
225 |
-
}
|
226 |
-
|
227 |
-
/**
|
228 |
-
* Appdend a string
|
229 |
-
*
|
230 |
-
* @param string $source
|
231 |
-
* @access public
|
232 |
-
*/
|
233 |
-
function appendString($source)
|
234 |
-
{
|
235 |
-
$this->tokenization = array('');
|
236 |
-
for ($i = 0; $i < strlen($source); $i++) {
|
237 |
-
if (strlen($this->ansi)) {
|
238 |
-
$this->ansi.= $source[$i];
|
239 |
-
$chr = ord($source[$i]);
|
240 |
-
// http://en.wikipedia.org/wiki/ANSI_escape_code#Sequence_elements
|
241 |
-
// single character CSI's not currently supported
|
242 |
-
switch (true) {
|
243 |
-
case $this->ansi == "\x1B=":
|
244 |
-
$this->ansi = '';
|
245 |
-
continue 2;
|
246 |
-
case strlen($this->ansi) == 2 && $chr >= 64 && $chr <= 95 && $chr != ord('['):
|
247 |
-
case strlen($this->ansi) > 2 && $chr >= 64 && $chr <= 126:
|
248 |
-
break;
|
249 |
-
default:
|
250 |
-
continue 2;
|
251 |
-
}
|
252 |
-
$this->tokenization[] = $this->ansi;
|
253 |
-
$this->tokenization[] = '';
|
254 |
-
// http://ascii-table.com/ansi-escape-sequences-vt-100.php
|
255 |
-
switch ($this->ansi) {
|
256 |
-
case "\x1B[H": // Move cursor to upper left corner
|
257 |
-
$this->old_x = $this->x;
|
258 |
-
$this->old_y = $this->y;
|
259 |
-
$this->x = $this->y = 0;
|
260 |
-
break;
|
261 |
-
case "\x1B[J": // Clear screen from cursor down
|
262 |
-
$this->history = array_merge($this->history, array_slice(array_splice($this->screen, $this->y + 1), 0, $this->old_y));
|
263 |
-
$this->screen = array_merge($this->screen, array_fill($this->y, $this->max_y, ''));
|
264 |
-
|
265 |
-
$this->history_attrs = array_merge($this->history_attrs, array_slice(array_splice($this->attrs, $this->y + 1), 0, $this->old_y));
|
266 |
-
$this->attrs = array_merge($this->attrs, array_fill($this->y, $this->max_y, $this->attr_row));
|
267 |
-
|
268 |
-
if (count($this->history) == $this->max_history) {
|
269 |
-
array_shift($this->history);
|
270 |
-
array_shift($this->history_attrs);
|
271 |
-
}
|
272 |
-
case "\x1B[K": // Clear screen from cursor right
|
273 |
-
$this->screen[$this->y] = substr($this->screen[$this->y], 0, $this->x);
|
274 |
-
|
275 |
-
array_splice($this->attrs[$this->y], $this->x + 1, $this->max_x - $this->x, array_fill($this->x, $this->max_x - $this->x - 1, $this->base_attr_cell));
|
276 |
-
break;
|
277 |
-
case "\x1B[2K": // Clear entire line
|
278 |
-
$this->screen[$this->y] = str_repeat(' ', $this->x);
|
279 |
-
$this->attrs[$this->y] = $this->attr_row;
|
280 |
-
break;
|
281 |
-
case "\x1B[?1h": // set cursor key to application
|
282 |
-
case "\x1B[?25h": // show the cursor
|
283 |
-
case "\x1B(B": // set united states g0 character set
|
284 |
-
break;
|
285 |
-
case "\x1BE": // Move to next line
|
286 |
-
$this->_newLine();
|
287 |
-
$this->x = 0;
|
288 |
-
break;
|
289 |
-
default:
|
290 |
-
switch (true) {
|
291 |
-
case preg_match('#\x1B\[(\d+)B#', $this->ansi, $match): // Move cursor down n lines
|
292 |
-
$this->old_y = $this->y;
|
293 |
-
$this->y+= $match[1];
|
294 |
-
break;
|
295 |
-
case preg_match('#\x1B\[(\d+);(\d+)H#', $this->ansi, $match): // Move cursor to screen location v,h
|
296 |
-
$this->old_x = $this->x;
|
297 |
-
$this->old_y = $this->y;
|
298 |
-
$this->x = $match[2] - 1;
|
299 |
-
$this->y = $match[1] - 1;
|
300 |
-
break;
|
301 |
-
case preg_match('#\x1B\[(\d+)C#', $this->ansi, $match): // Move cursor right n lines
|
302 |
-
$this->old_x = $this->x;
|
303 |
-
$this->x+= $match[1];
|
304 |
-
break;
|
305 |
-
case preg_match('#\x1B\[(\d+)D#', $this->ansi, $match): // Move cursor left n lines
|
306 |
-
$this->old_x = $this->x;
|
307 |
-
$this->x-= $match[1];
|
308 |
-
if ($this->x < 0) {
|
309 |
-
$this->x = 0;
|
310 |
-
}
|
311 |
-
break;
|
312 |
-
case preg_match('#\x1B\[(\d+);(\d+)r#', $this->ansi, $match): // Set top and bottom lines of a window
|
313 |
-
break;
|
314 |
-
case preg_match('#\x1B\[(\d*(?:;\d*)*)m#', $this->ansi, $match): // character attributes
|
315 |
-
$attr_cell = &$this->attr_cell;
|
316 |
-
$mods = explode(';', $match[1]);
|
317 |
-
foreach ($mods as $mod) {
|
318 |
-
switch ($mod) {
|
319 |
-
case 0: // Turn off character attributes
|
320 |
-
$attr_cell = clone $this->base_attr_cell;
|
321 |
-
break;
|
322 |
-
case 1: // Turn bold mode on
|
323 |
-
$attr_cell->bold = true;
|
324 |
-
break;
|
325 |
-
case 4: // Turn underline mode on
|
326 |
-
$attr_cell->underline = true;
|
327 |
-
break;
|
328 |
-
case 5: // Turn blinking mode on
|
329 |
-
$attr_cell->blink = true;
|
330 |
-
break;
|
331 |
-
case 7: // Turn reverse video on
|
332 |
-
$attr_cell->reverse = !$attr_cell->reverse;
|
333 |
-
$temp = $attr_cell->background;
|
334 |
-
$attr_cell->background = $attr_cell->foreground;
|
335 |
-
$attr_cell->foreground = $temp;
|
336 |
-
break;
|
337 |
-
default: // set colors
|
338 |
-
//$front = $attr_cell->reverse ? &$attr_cell->background : &$attr_cell->foreground;
|
339 |
-
$front = &$attr_cell->{ $attr_cell->reverse ? 'background' : 'foreground' };
|
340 |
-
//$back = $attr_cell->reverse ? &$attr_cell->foreground : &$attr_cell->background;
|
341 |
-
$back = &$attr_cell->{ $attr_cell->reverse ? 'foreground' : 'background' };
|
342 |
-
switch ($mod) {
|
343 |
-
// @codingStandardsIgnoreStart
|
344 |
-
case 30: $front = 'black'; break;
|
345 |
-
case 31: $front = 'red'; break;
|
346 |
-
case 32: $front = 'green'; break;
|
347 |
-
case 33: $front = 'yellow'; break;
|
348 |
-
case 34: $front = 'blue'; break;
|
349 |
-
case 35: $front = 'magenta'; break;
|
350 |
-
case 36: $front = 'cyan'; break;
|
351 |
-
case 37: $front = 'white'; break;
|
352 |
-
|
353 |
-
case 40: $back = 'black'; break;
|
354 |
-
case 41: $back = 'red'; break;
|
355 |
-
case 42: $back = 'green'; break;
|
356 |
-
case 43: $back = 'yellow'; break;
|
357 |
-
case 44: $back = 'blue'; break;
|
358 |
-
case 45: $back = 'magenta'; break;
|
359 |
-
case 46: $back = 'cyan'; break;
|
360 |
-
case 47: $back = 'white'; break;
|
361 |
-
// @codingStandardsIgnoreEnd
|
362 |
-
|
363 |
-
default:
|
364 |
-
//user_error('Unsupported attribute: ' . $mod);
|
365 |
-
$this->ansi = '';
|
366 |
-
break 2;
|
367 |
-
}
|
368 |
-
}
|
369 |
-
}
|
370 |
-
break;
|
371 |
-
default:
|
372 |
-
//user_error("{$this->ansi} is unsupported\r\n");
|
373 |
-
}
|
374 |
-
}
|
375 |
-
$this->ansi = '';
|
376 |
-
continue;
|
377 |
-
}
|
378 |
-
|
379 |
-
$this->tokenization[count($this->tokenization) - 1].= $source[$i];
|
380 |
-
switch ($source[$i]) {
|
381 |
-
case "\r":
|
382 |
-
$this->x = 0;
|
383 |
-
break;
|
384 |
-
case "\n":
|
385 |
-
$this->_newLine();
|
386 |
-
break;
|
387 |
-
case "\x08": // backspace
|
388 |
-
if ($this->x) {
|
389 |
-
$this->x--;
|
390 |
-
$this->attrs[$this->y][$this->x] = clone $this->base_attr_cell;
|
391 |
-
$this->screen[$this->y] = substr_replace(
|
392 |
-
$this->screen[$this->y],
|
393 |
-
$source[$i],
|
394 |
-
$this->x,
|
395 |
-
1
|
396 |
-
);
|
397 |
-
}
|
398 |
-
break;
|
399 |
-
case "\x0F": // shift
|
400 |
-
break;
|
401 |
-
case "\x1B": // start ANSI escape code
|
402 |
-
$this->tokenization[count($this->tokenization) - 1] = substr($this->tokenization[count($this->tokenization) - 1], 0, -1);
|
403 |
-
//if (!strlen($this->tokenization[count($this->tokenization) - 1])) {
|
404 |
-
// array_pop($this->tokenization);
|
405 |
-
//}
|
406 |
-
$this->ansi.= "\x1B";
|
407 |
-
break;
|
408 |
-
default:
|
409 |
-
$this->attrs[$this->y][$this->x] = clone $this->attr_cell;
|
410 |
-
if ($this->x > strlen($this->screen[$this->y])) {
|
411 |
-
$this->screen[$this->y] = str_repeat(' ', $this->x);
|
412 |
-
}
|
413 |
-
$this->screen[$this->y] = substr_replace(
|
414 |
-
$this->screen[$this->y],
|
415 |
-
$source[$i],
|
416 |
-
$this->x,
|
417 |
-
1
|
418 |
-
);
|
419 |
-
|
420 |
-
if ($this->x > $this->max_x) {
|
421 |
-
$this->x = 0;
|
422 |
-
$this->_newLine();
|
423 |
-
} else {
|
424 |
-
$this->x++;
|
425 |
-
}
|
426 |
-
}
|
427 |
-
}
|
428 |
-
}
|
429 |
-
|
430 |
-
/**
|
431 |
-
* Add a new line
|
432 |
-
*
|
433 |
-
* Also update the $this->screen and $this->history buffers
|
434 |
-
*
|
435 |
-
* @access private
|
436 |
-
*/
|
437 |
-
function _newLine()
|
438 |
-
{
|
439 |
-
//if ($this->y < $this->max_y) {
|
440 |
-
// $this->y++;
|
441 |
-
//}
|
442 |
-
|
443 |
-
while ($this->y >= $this->max_y) {
|
444 |
-
$this->history = array_merge($this->history, array(array_shift($this->screen)));
|
445 |
-
$this->screen[] = '';
|
446 |
-
|
447 |
-
$this->history_attrs = array_merge($this->history_attrs, array(array_shift($this->attrs)));
|
448 |
-
$this->attrs[] = $this->attr_row;
|
449 |
-
|
450 |
-
if (count($this->history) >= $this->max_history) {
|
451 |
-
array_shift($this->history);
|
452 |
-
array_shift($this->history_attrs);
|
453 |
-
}
|
454 |
-
|
455 |
-
$this->y--;
|
456 |
-
}
|
457 |
-
$this->y++;
|
458 |
-
}
|
459 |
-
|
460 |
-
/**
|
461 |
-
* Returns the current coordinate without preformating
|
462 |
-
*
|
463 |
-
* @access private
|
464 |
-
* @return string
|
465 |
-
*/
|
466 |
-
function _processCoordinate($last_attr, $cur_attr, $char)
|
467 |
-
{
|
468 |
-
$output = '';
|
469 |
-
|
470 |
-
if ($last_attr != $cur_attr) {
|
471 |
-
$close = $open = '';
|
472 |
-
if ($last_attr->foreground != $cur_attr->foreground) {
|
473 |
-
if ($cur_attr->foreground != 'white') {
|
474 |
-
$open.= '<span style="color: ' . $cur_attr->foreground . '">';
|
475 |
-
}
|
476 |
-
if ($last_attr->foreground != 'white') {
|
477 |
-
$close = '</span>' . $close;
|
478 |
-
}
|
479 |
-
}
|
480 |
-
if ($last_attr->background != $cur_attr->background) {
|
481 |
-
if ($cur_attr->background != 'black') {
|
482 |
-
$open.= '<span style="background: ' . $cur_attr->background . '">';
|
483 |
-
}
|
484 |
-
if ($last_attr->background != 'black') {
|
485 |
-
$close = '</span>' . $close;
|
486 |
-
}
|
487 |
-
}
|
488 |
-
if ($last_attr->bold != $cur_attr->bold) {
|
489 |
-
if ($cur_attr->bold) {
|
490 |
-
$open.= '<b>';
|
491 |
-
} else {
|
492 |
-
$close = '</b>' . $close;
|
493 |
-
}
|
494 |
-
}
|
495 |
-
if ($last_attr->underline != $cur_attr->underline) {
|
496 |
-
if ($cur_attr->underline) {
|
497 |
-
$open.= '<u>';
|
498 |
-
} else {
|
499 |
-
$close = '</u>' . $close;
|
500 |
-
}
|
501 |
-
}
|
502 |
-
if ($last_attr->blink != $cur_attr->blink) {
|
503 |
-
if ($cur_attr->blink) {
|
504 |
-
$open.= '<blink>';
|
505 |
-
} else {
|
506 |
-
$close = '</blink>' . $close;
|
507 |
-
}
|
508 |
-
}
|
509 |
-
$output.= $close . $open;
|
510 |
-
}
|
511 |
-
|
512 |
-
$output.= htmlspecialchars($char);
|
513 |
-
|
514 |
-
return $output;
|
515 |
-
}
|
516 |
-
|
517 |
-
/**
|
518 |
-
* Returns the current screen without preformating
|
519 |
-
*
|
520 |
-
* @access private
|
521 |
-
* @return string
|
522 |
-
*/
|
523 |
-
function _getScreen()
|
524 |
-
{
|
525 |
-
$output = '';
|
526 |
-
$last_attr = $this->base_attr_cell;
|
527 |
-
for ($i = 0; $i <= $this->max_y; $i++) {
|
528 |
-
for ($j = 0; $j <= $this->max_x; $j++) {
|
529 |
-
$cur_attr = $this->attrs[$i][$j];
|
530 |
-
$output.= $this->_processCoordinate($last_attr, $cur_attr, isset($this->screen[$i][$j]) ? $this->screen[$i][$j] : '');
|
531 |
-
$last_attr = $this->attrs[$i][$j];
|
532 |
-
}
|
533 |
-
$output.= "\r\n";
|
534 |
-
}
|
535 |
-
$output = substr($output, 0, -2);
|
536 |
-
// close any remaining open tags
|
537 |
-
$output.= $this->_processCoordinate($last_attr, $this->base_attr_cell, '');
|
538 |
-
return rtrim($output);
|
539 |
-
}
|
540 |
-
|
541 |
-
/**
|
542 |
-
* Returns the current screen
|
543 |
-
*
|
544 |
-
* @access public
|
545 |
-
* @return string
|
546 |
-
*/
|
547 |
-
function getScreen()
|
548 |
-
{
|
549 |
-
return '<pre width="' . ($this->max_x + 1) . '" style="color: white; background: black">' . $this->_getScreen() . '</pre>';
|
550 |
-
}
|
551 |
-
|
552 |
-
/**
|
553 |
-
* Returns the current screen and the x previous lines
|
554 |
-
*
|
555 |
-
* @access public
|
556 |
-
* @return string
|
557 |
-
*/
|
558 |
-
function getHistory()
|
559 |
-
{
|
560 |
-
$scrollback = '';
|
561 |
-
$last_attr = $this->base_attr_cell;
|
562 |
-
for ($i = 0; $i < count($this->history); $i++) {
|
563 |
-
for ($j = 0; $j <= $this->max_x + 1; $j++) {
|
564 |
-
$cur_attr = $this->history_attrs[$i][$j];
|
565 |
-
$scrollback.= $this->_processCoordinate($last_attr, $cur_attr, isset($this->history[$i][$j]) ? $this->history[$i][$j] : '');
|
566 |
-
$last_attr = $this->history_attrs[$i][$j];
|
567 |
-
}
|
568 |
-
$scrollback.= "\r\n";
|
569 |
-
}
|
570 |
-
$base_attr_cell = $this->base_attr_cell;
|
571 |
-
$this->base_attr_cell = $last_attr;
|
572 |
-
$scrollback.= $this->_getScreen();
|
573 |
-
$this->base_attr_cell = $base_attr_cell;
|
574 |
-
|
575 |
-
return '<pre width="' . ($this->max_x + 1) . '" style="color: white; background: black">' . $scrollback . '</span></pre>';
|
576 |
-
}
|
577 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php
DELETED
@@ -1,1325 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Pure-PHP ASN.1 Parser
|
5 |
-
*
|
6 |
-
* PHP version 5
|
7 |
-
*
|
8 |
-
* ASN.1 provides the semantics for data encoded using various schemes. The most commonly
|
9 |
-
* utilized scheme is DER or the "Distinguished Encoding Rules". PEM's are base64 encoded
|
10 |
-
* DER blobs.
|
11 |
-
*
|
12 |
-
* \phpseclib\File\ASN1 decodes and encodes DER formatted messages and places them in a semantic context.
|
13 |
-
*
|
14 |
-
* Uses the 1988 ASN.1 syntax.
|
15 |
-
*
|
16 |
-
* @category File
|
17 |
-
* @package ASN1
|
18 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
19 |
-
* @copyright 2012 Jim Wigginton
|
20 |
-
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
21 |
-
* @link http://phpseclib.sourceforge.net
|
22 |
-
*/
|
23 |
-
|
24 |
-
namespace phpseclib\File;
|
25 |
-
|
26 |
-
use phpseclib\File\ASN1\Element;
|
27 |
-
use phpseclib\Math\BigInteger;
|
28 |
-
use DateTime;
|
29 |
-
use DateTimeZone;
|
30 |
-
|
31 |
-
/**
|
32 |
-
* Pure-PHP ASN.1 Parser
|
33 |
-
*
|
34 |
-
* @package ASN1
|
35 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
36 |
-
* @access public
|
37 |
-
*/
|
38 |
-
class ASN1
|
39 |
-
{
|
40 |
-
/**#@+
|
41 |
-
* Tag Classes
|
42 |
-
*
|
43 |
-
* @access private
|
44 |
-
* @link http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=12
|
45 |
-
*/
|
46 |
-
const CLASS_UNIVERSAL = 0;
|
47 |
-
const CLASS_APPLICATION = 1;
|
48 |
-
const CLASS_CONTEXT_SPECIFIC = 2;
|
49 |
-
const CLASS_PRIVATE = 3;
|
50 |
-
/**#@-*/
|
51 |
-
|
52 |
-
/**#@+
|
53 |
-
* Tag Classes
|
54 |
-
*
|
55 |
-
* @access private
|
56 |
-
* @link http://www.obj-sys.com/asn1tutorial/node124.html
|
57 |
-
*/
|
58 |
-
const TYPE_BOOLEAN = 1;
|
59 |
-
const TYPE_INTEGER = 2;
|
60 |
-
const TYPE_BIT_STRING = 3;
|
61 |
-
const TYPE_OCTET_STRING = 4;
|
62 |
-
const TYPE_NULL = 5;
|
63 |
-
const TYPE_OBJECT_IDENTIFIER = 6;
|
64 |
-
//const TYPE_OBJECT_DESCRIPTOR = 7;
|
65 |
-
//const TYPE_INSTANCE_OF = 8; // EXTERNAL
|
66 |
-
const TYPE_REAL = 9;
|
67 |
-
const TYPE_ENUMERATED = 10;
|
68 |
-
//const TYPE_EMBEDDED = 11;
|
69 |
-
const TYPE_UTF8_STRING = 12;
|
70 |
-
//const TYPE_RELATIVE_OID = 13;
|
71 |
-
const TYPE_SEQUENCE = 16; // SEQUENCE OF
|
72 |
-
const TYPE_SET = 17; // SET OF
|
73 |
-
/**#@-*/
|
74 |
-
/**#@+
|
75 |
-
* More Tag Classes
|
76 |
-
*
|
77 |
-
* @access private
|
78 |
-
* @link http://www.obj-sys.com/asn1tutorial/node10.html
|
79 |
-
*/
|
80 |
-
const TYPE_NUMERIC_STRING = 18;
|
81 |
-
const TYPE_PRINTABLE_STRING = 19;
|
82 |
-
const TYPE_TELETEX_STRING = 20; // T61String
|
83 |
-
const TYPE_VIDEOTEX_STRING = 21;
|
84 |
-
const TYPE_IA5_STRING = 22;
|
85 |
-
const TYPE_UTC_TIME = 23;
|
86 |
-
const TYPE_GENERALIZED_TIME = 24;
|
87 |
-
const TYPE_GRAPHIC_STRING = 25;
|
88 |
-
const TYPE_VISIBLE_STRING = 26; // ISO646String
|
89 |
-
const TYPE_GENERAL_STRING = 27;
|
90 |
-
const TYPE_UNIVERSAL_STRING = 28;
|
91 |
-
//const TYPE_CHARACTER_STRING = 29;
|
92 |
-
const TYPE_BMP_STRING = 30;
|
93 |
-
/**#@-*/
|
94 |
-
|
95 |
-
/**#@+
|
96 |
-
* Tag Aliases
|
97 |
-
*
|
98 |
-
* These tags are kinda place holders for other tags.
|
99 |
-
*
|
100 |
-
* @access private
|
101 |
-
*/
|
102 |
-
const TYPE_CHOICE = -1;
|
103 |
-
const TYPE_ANY = -2;
|
104 |
-
/**#@-*/
|
105 |
-
|
106 |
-
/**
|
107 |
-
* ASN.1 object identifier
|
108 |
-
*
|
109 |
-
* @var array
|
110 |
-
* @access private
|
111 |
-
* @link http://en.wikipedia.org/wiki/Object_identifier
|
112 |
-
*/
|
113 |
-
var $oids = array();
|
114 |
-
|
115 |
-
/**
|
116 |
-
* Default date format
|
117 |
-
*
|
118 |
-
* @var string
|
119 |
-
* @access private
|
120 |
-
* @link http://php.net/class.datetime
|
121 |
-
*/
|
122 |
-
var $format = 'D, d M Y H:i:s O';
|
123 |
-
|
124 |
-
/**
|
125 |
-
* Default date format
|
126 |
-
*
|
127 |
-
* @var array
|
128 |
-
* @access private
|
129 |
-
* @see self::setTimeFormat()
|
130 |
-
* @see self::asn1map()
|
131 |
-
* @link http://php.net/class.datetime
|
132 |
-
*/
|
133 |
-
var $encoded;
|
134 |
-
|
135 |
-
/**
|
136 |
-
* Filters
|
137 |
-
*
|
138 |
-
* If the mapping type is self::TYPE_ANY what do we actually encode it as?
|
139 |
-
*
|
140 |
-
* @var array
|
141 |
-
* @access private
|
142 |
-
* @see self::_encode_der()
|
143 |
-
*/
|
144 |
-
var $filters;
|
145 |
-
|
146 |
-
/**
|
147 |
-
* Type mapping table for the ANY type.
|
148 |
-
*
|
149 |
-
* Structured or unknown types are mapped to a \phpseclib\File\ASN1\Element.
|
150 |
-
* Unambiguous types get the direct mapping (int/real/bool).
|
151 |
-
* Others are mapped as a choice, with an extra indexing level.
|
152 |
-
*
|
153 |
-
* @var array
|
154 |
-
* @access public
|
155 |
-
*/
|
156 |
-
var $ANYmap = array(
|
157 |
-
self::TYPE_BOOLEAN => true,
|
158 |
-
self::TYPE_INTEGER => true,
|
159 |
-
self::TYPE_BIT_STRING => 'bitString',
|
160 |
-
self::TYPE_OCTET_STRING => 'octetString',
|
161 |
-
self::TYPE_NULL => 'null',
|
162 |
-
self::TYPE_OBJECT_IDENTIFIER => 'objectIdentifier',
|
163 |
-
self::TYPE_REAL => true,
|
164 |
-
self::TYPE_ENUMERATED => 'enumerated',
|
165 |
-
self::TYPE_UTF8_STRING => 'utf8String',
|
166 |
-
self::TYPE_NUMERIC_STRING => 'numericString',
|
167 |
-
self::TYPE_PRINTABLE_STRING => 'printableString',
|
168 |
-
self::TYPE_TELETEX_STRING => 'teletexString',
|
169 |
-
self::TYPE_VIDEOTEX_STRING => 'videotexString',
|
170 |
-
self::TYPE_IA5_STRING => 'ia5String',
|
171 |
-
self::TYPE_UTC_TIME => 'utcTime',
|
172 |
-
self::TYPE_GENERALIZED_TIME => 'generalTime',
|
173 |
-
self::TYPE_GRAPHIC_STRING => 'graphicString',
|
174 |
-
self::TYPE_VISIBLE_STRING => 'visibleString',
|
175 |
-
self::TYPE_GENERAL_STRING => 'generalString',
|
176 |
-
self::TYPE_UNIVERSAL_STRING => 'universalString',
|
177 |
-
//self::TYPE_CHARACTER_STRING => 'characterString',
|
178 |
-
self::TYPE_BMP_STRING => 'bmpString'
|
179 |
-
);
|
180 |
-
|
181 |
-
/**
|
182 |
-
* String type to character size mapping table.
|
183 |
-
*
|
184 |
-
* Non-convertable types are absent from this table.
|
185 |
-
* size == 0 indicates variable length encoding.
|
186 |
-
*
|
187 |
-
* @var array
|
188 |
-
* @access public
|
189 |
-
*/
|
190 |
-
var $stringTypeSize = array(
|
191 |
-
self::TYPE_UTF8_STRING => 0,
|
192 |
-
self::TYPE_BMP_STRING => 2,
|
193 |
-
self::TYPE_UNIVERSAL_STRING => 4,
|
194 |
-
self::TYPE_PRINTABLE_STRING => 1,
|
195 |
-
self::TYPE_TELETEX_STRING => 1,
|
196 |
-
self::TYPE_IA5_STRING => 1,
|
197 |
-
self::TYPE_VISIBLE_STRING => 1,
|
198 |
-
);
|
199 |
-
|
200 |
-
/**
|
201 |
-
* Parse BER-encoding
|
202 |
-
*
|
203 |
-
* Serves a similar purpose to openssl's asn1parse
|
204 |
-
*
|
205 |
-
* @param string $encoded
|
206 |
-
* @return array
|
207 |
-
* @access public
|
208 |
-
*/
|
209 |
-
function decodeBER($encoded)
|
210 |
-
{
|
211 |
-
if ($encoded instanceof Element) {
|
212 |
-
$encoded = $encoded->element;
|
213 |
-
}
|
214 |
-
|
215 |
-
$this->encoded = $encoded;
|
216 |
-
// encapsulate in an array for BC with the old decodeBER
|
217 |
-
return array($this->_decode_ber($encoded));
|
218 |
-
}
|
219 |
-
|
220 |
-
/**
|
221 |
-
* Parse BER-encoding (Helper function)
|
222 |
-
*
|
223 |
-
* Sometimes we want to get the BER encoding of a particular tag. $start lets us do that without having to reencode.
|
224 |
-
* $encoded is passed by reference for the recursive calls done for self::TYPE_BIT_STRING and
|
225 |
-
* self::TYPE_OCTET_STRING. In those cases, the indefinite length is used.
|
226 |
-
*
|
227 |
-
* @param string $encoded
|
228 |
-
* @param int $start
|
229 |
-
* @param int $encoded_pos
|
230 |
-
* @return array
|
231 |
-
* @access private
|
232 |
-
*/
|
233 |
-
function _decode_ber($encoded, $start = 0, $encoded_pos = 0)
|
234 |
-
{
|
235 |
-
$current = array('start' => $start);
|
236 |
-
|
237 |
-
$type = ord($encoded[$encoded_pos++]);
|
238 |
-
$start++;
|
239 |
-
|
240 |
-
$constructed = ($type >> 5) & 1;
|
241 |
-
|
242 |
-
$tag = $type & 0x1F;
|
243 |
-
if ($tag == 0x1F) {
|
244 |
-
$tag = 0;
|
245 |
-
// process septets (since the eighth bit is ignored, it's not an octet)
|
246 |
-
do {
|
247 |
-
$loop = ord($encoded[0]) >> 7;
|
248 |
-
$tag <<= 7;
|
249 |
-
$tag |= ord($encoded[$encoded_pos++]) & 0x7F;
|
250 |
-
$start++;
|
251 |
-
} while ($loop);
|
252 |
-
}
|
253 |
-
|
254 |
-
// Length, as discussed in paragraph 8.1.3 of X.690-0207.pdf#page=13
|
255 |
-
$length = ord($encoded[$encoded_pos++]);
|
256 |
-
$start++;
|
257 |
-
if ($length == 0x80) { // indefinite length
|
258 |
-
// "[A sender shall] use the indefinite form (see 8.1.3.6) if the encoding is constructed and is not all
|
259 |
-
// immediately available." -- paragraph 8.1.3.2.c
|
260 |
-
$length = strlen($encoded) - $encoded_pos;
|
261 |
-
} elseif ($length & 0x80) { // definite length, long form
|
262 |
-
// technically, the long form of the length can be represented by up to 126 octets (bytes), but we'll only
|
263 |
-
// support it up to four.
|
264 |
-
$length&= 0x7F;
|
265 |
-
$temp = substr($encoded, $encoded_pos, $length);
|
266 |
-
$encoded_pos += $length;
|
267 |
-
// tags of indefinte length don't really have a header length; this length includes the tag
|
268 |
-
$current+= array('headerlength' => $length + 2);
|
269 |
-
$start+= $length;
|
270 |
-
extract(unpack('Nlength', substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4)));
|
271 |
-
} else {
|
272 |
-
$current+= array('headerlength' => 2);
|
273 |
-
}
|
274 |
-
|
275 |
-
if ($length > (strlen($encoded) - $encoded_pos)) {
|
276 |
-
return false;
|
277 |
-
}
|
278 |
-
|
279 |
-
$content = substr($encoded, $encoded_pos, $length);
|
280 |
-
$content_pos = 0;
|
281 |
-
|
282 |
-
// at this point $length can be overwritten. it's only accurate for definite length things as is
|
283 |
-
|
284 |
-
/* Class is UNIVERSAL, APPLICATION, PRIVATE, or CONTEXT-SPECIFIC. The UNIVERSAL class is restricted to the ASN.1
|
285 |
-
built-in types. It defines an application-independent data type that must be distinguishable from all other
|
286 |
-
data types. The other three classes are user defined. The APPLICATION class distinguishes data types that
|
287 |
-
have a wide, scattered use within a particular presentation context. PRIVATE distinguishes data types within
|
288 |
-
a particular organization or country. CONTEXT-SPECIFIC distinguishes members of a sequence or set, the
|
289 |
-
alternatives of a CHOICE, or universally tagged set members. Only the class number appears in braces for this
|
290 |
-
data type; the term CONTEXT-SPECIFIC does not appear.
|
291 |
-
|
292 |
-
-- http://www.obj-sys.com/asn1tutorial/node12.html */
|
293 |
-
$class = ($type >> 6) & 3;
|
294 |
-
switch ($class) {
|
295 |
-
case self::CLASS_APPLICATION:
|
296 |
-
case self::CLASS_PRIVATE:
|
297 |
-
case self::CLASS_CONTEXT_SPECIFIC:
|
298 |
-
if (!$constructed) {
|
299 |
-
return array(
|
300 |
-
'type' => $class,
|
301 |
-
'constant' => $tag,
|
302 |
-
'content' => $content,
|
303 |
-
'length' => $length + $start - $current['start']
|
304 |
-
);
|
305 |
-
}
|
306 |
-
|
307 |
-
$newcontent = array();
|
308 |
-
$remainingLength = $length;
|
309 |
-
while ($remainingLength > 0) {
|
310 |
-
$temp = $this->_decode_ber($content, $start, $content_pos);
|
311 |
-
$length = $temp['length'];
|
312 |
-
// end-of-content octets - see paragraph 8.1.5
|
313 |
-
if (substr($content, $content_pos + $length, 2) == "\0\0") {
|
314 |
-
$length+= 2;
|
315 |
-
$start+= $length;
|
316 |
-
$newcontent[] = $temp;
|
317 |
-
break;
|
318 |
-
}
|
319 |
-
$start+= $length;
|
320 |
-
$remainingLength-= $length;
|
321 |
-
$newcontent[] = $temp;
|
322 |
-
$content_pos += $length;
|
323 |
-
}
|
324 |
-
|
325 |
-
return array(
|
326 |
-
'type' => $class,
|
327 |
-
'constant' => $tag,
|
328 |
-
// the array encapsulation is for BC with the old format
|
329 |
-
'content' => $newcontent,
|
330 |
-
// the only time when $content['headerlength'] isn't defined is when the length is indefinite.
|
331 |
-
// the absence of $content['headerlength'] is how we know if something is indefinite or not.
|
332 |
-
// technically, it could be defined to be 2 and then another indicator could be used but whatever.
|
333 |
-
'length' => $start - $current['start']
|
334 |
-
) + $current;
|
335 |
-
}
|
336 |
-
|
337 |
-
$current+= array('type' => $tag);
|
338 |
-
|
339 |
-
// decode UNIVERSAL tags
|
340 |
-
switch ($tag) {
|
341 |
-
case self::TYPE_BOOLEAN:
|
342 |
-
// "The contents octets shall consist of a single octet." -- paragraph 8.2.1
|
343 |
-
//if (strlen($content) != 1) {
|
344 |
-
// return false;
|
345 |
-
//}
|
346 |
-
$current['content'] = (bool) ord($content[$content_pos]);
|
347 |
-
break;
|
348 |
-
case self::TYPE_INTEGER:
|
349 |
-
case self::TYPE_ENUMERATED:
|
350 |
-
$current['content'] = new BigInteger(substr($content, $content_pos), -256);
|
351 |
-
break;
|
352 |
-
case self::TYPE_REAL: // not currently supported
|
353 |
-
return false;
|
354 |
-
case self::TYPE_BIT_STRING:
|
355 |
-
// The initial octet shall encode, as an unsigned binary integer with bit 1 as the least significant bit,
|
356 |
-
// the number of unused bits in the final subsequent octet. The number shall be in the range zero to
|
357 |
-
// seven.
|
358 |
-
if (!$constructed) {
|
359 |
-
$current['content'] = substr($content, $content_pos);
|
360 |
-
} else {
|
361 |
-
$temp = $this->_decode_ber($content, $start, $content_pos);
|
362 |
-
$length-= (strlen($content) - $content_pos);
|
363 |
-
$last = count($temp) - 1;
|
364 |
-
for ($i = 0; $i < $last; $i++) {
|
365 |
-
// all subtags should be bit strings
|
366 |
-
//if ($temp[$i]['type'] != self::TYPE_BIT_STRING) {
|
367 |
-
// return false;
|
368 |
-
//}
|
369 |
-
$current['content'].= substr($temp[$i]['content'], 1);
|
370 |
-
}
|
371 |
-
// all subtags should be bit strings
|
372 |
-
//if ($temp[$last]['type'] != self::TYPE_BIT_STRING) {
|
373 |
-
// return false;
|
374 |
-
//}
|
375 |
-
$current['content'] = $temp[$last]['content'][0] . $current['content'] . substr($temp[$i]['content'], 1);
|
376 |
-
}
|
377 |
-
break;
|
378 |
-
case self::TYPE_OCTET_STRING:
|
379 |
-
if (!$constructed) {
|
380 |
-
$current['content'] = substr($content, $content_pos);
|
381 |
-
} else {
|
382 |
-
$current['content'] = '';
|
383 |
-
$length = 0;
|
384 |
-
while (substr($content, $content_pos, 2) != "\0\0") {
|
385 |
-
$temp = $this->_decode_ber($content, $length + $start, $content_pos);
|
386 |
-
$content_pos += $temp['length'];
|
387 |
-
// all subtags should be octet strings
|
388 |
-
//if ($temp['type'] != self::TYPE_OCTET_STRING) {
|
389 |
-
// return false;
|
390 |
-
//}
|
391 |
-
$current['content'].= $temp['content'];
|
392 |
-
$length+= $temp['length'];
|
393 |
-
}
|
394 |
-
if (substr($content, $content_pos, 2) == "\0\0") {
|
395 |
-
$length+= 2; // +2 for the EOC
|
396 |
-
}
|
397 |
-
}
|
398 |
-
break;
|
399 |
-
case self::TYPE_NULL:
|
400 |
-
// "The contents octets shall not contain any octets." -- paragraph 8.8.2
|
401 |
-
//if (strlen($content)) {
|
402 |
-
// return false;
|
403 |
-
//}
|
404 |
-
break;
|
405 |
-
case self::TYPE_SEQUENCE:
|
406 |
-
case self::TYPE_SET:
|
407 |
-
$offset = 0;
|
408 |
-
$current['content'] = array();
|
409 |
-
$content_len = strlen($content);
|
410 |
-
while ($content_pos < $content_len) {
|
411 |
-
// if indefinite length construction was used and we have an end-of-content string next
|
412 |
-
// see paragraphs 8.1.1.3, 8.1.3.2, 8.1.3.6, 8.1.5, and (for an example) 8.6.4.2
|
413 |
-
if (!isset($current['headerlength']) && substr($content, $content_pos, 2) == "\0\0") {
|
414 |
-
$length = $offset + 2; // +2 for the EOC
|
415 |
-
break 2;
|
416 |
-
}
|
417 |
-
$temp = $this->_decode_ber($content, $start + $offset, $content_pos);
|
418 |
-
$content_pos += $temp['length'];
|
419 |
-
$current['content'][] = $temp;
|
420 |
-
$offset+= $temp['length'];
|
421 |
-
}
|
422 |
-
break;
|
423 |
-
case self::TYPE_OBJECT_IDENTIFIER:
|
424 |
-
$temp = ord($content[$content_pos++]);
|
425 |
-
$current['content'] = sprintf('%d.%d', floor($temp / 40), $temp % 40);
|
426 |
-
$valuen = 0;
|
427 |
-
// process septets
|
428 |
-
$content_len = strlen($content);
|
429 |
-
while ($content_pos < $content_len) {
|
430 |
-
$temp = ord($content[$content_pos++]);
|
431 |
-
$valuen <<= 7;
|
432 |
-
$valuen |= $temp & 0x7F;
|
433 |
-
if (~$temp & 0x80) {
|
434 |
-
$current['content'].= ".$valuen";
|
435 |
-
$valuen = 0;
|
436 |
-
}
|
437 |
-
}
|
438 |
-
// the eighth bit of the last byte should not be 1
|
439 |
-
//if ($temp >> 7) {
|
440 |
-
// return false;
|
441 |
-
//}
|
442 |
-
break;
|
443 |
-
/* Each character string type shall be encoded as if it had been declared:
|
444 |
-
[UNIVERSAL x] IMPLICIT OCTET STRING
|
445 |
-
|
446 |
-
-- X.690-0207.pdf#page=23 (paragraph 8.21.3)
|
447 |
-
|
448 |
-
Per that, we're not going to do any validation. If there are any illegal characters in the string,
|
449 |
-
we don't really care */
|
450 |
-
case self::TYPE_NUMERIC_STRING:
|
451 |
-
// 0,1,2,3,4,5,6,7,8,9, and space
|
452 |
-
case self::TYPE_PRINTABLE_STRING:
|
453 |
-
// Upper and lower case letters, digits, space, apostrophe, left/right parenthesis, plus sign, comma,
|
454 |
-
// hyphen, full stop, solidus, colon, equal sign, question mark
|
455 |
-
case self::TYPE_TELETEX_STRING:
|
456 |
-
// The Teletex character set in CCITT's T61, space, and delete
|
457 |
-
// see http://en.wikipedia.org/wiki/Teletex#Character_sets
|
458 |
-
case self::TYPE_VIDEOTEX_STRING:
|
459 |
-
// The Videotex character set in CCITT's T.100 and T.101, space, and delete
|
460 |
-
case self::TYPE_VISIBLE_STRING:
|
461 |
-
// Printing character sets of international ASCII, and space
|
462 |
-
case self::TYPE_IA5_STRING:
|
463 |
-
// International Alphabet 5 (International ASCII)
|
464 |
-
case self::TYPE_GRAPHIC_STRING:
|
465 |
-
// All registered G sets, and space
|
466 |
-
case self::TYPE_GENERAL_STRING:
|
467 |
-
// All registered C and G sets, space and delete
|
468 |
-
case self::TYPE_UTF8_STRING:
|
469 |
-
// ????
|
470 |
-
case self::TYPE_BMP_STRING:
|
471 |
-
$current['content'] = substr($content, $content_pos);
|
472 |
-
break;
|
473 |
-
case self::TYPE_UTC_TIME:
|
474 |
-
case self::TYPE_GENERALIZED_TIME:
|
475 |
-
$current['content'] = $this->_decodeTime(substr($content, $content_pos), $tag);
|
476 |
-
default:
|
477 |
-
}
|
478 |
-
|
479 |
-
$start+= $length;
|
480 |
-
|
481 |
-
// ie. length is the length of the full TLV encoding - it's not just the length of the value
|
482 |
-
return $current + array('length' => $start - $current['start']);
|
483 |
-
}
|
484 |
-
|
485 |
-
/**
|
486 |
-
* ASN.1 Map
|
487 |
-
*
|
488 |
-
* Provides an ASN.1 semantic mapping ($mapping) from a parsed BER-encoding to a human readable format.
|
489 |
-
*
|
490 |
-
* "Special" mappings may be applied on a per tag-name basis via $special.
|
491 |
-
*
|
492 |
-
* @param array $decoded
|
493 |
-
* @param array $mapping
|
494 |
-
* @param array $special
|
495 |
-
* @return array
|
496 |
-
* @access public
|
497 |
-
*/
|
498 |
-
function asn1map($decoded, $mapping, $special = array())
|
499 |
-
{
|
500 |
-
if (isset($mapping['explicit']) && is_array($decoded['content'])) {
|
501 |
-
$decoded = $decoded['content'][0];
|
502 |
-
}
|
503 |
-
|
504 |
-
switch (true) {
|
505 |
-
case $mapping['type'] == self::TYPE_ANY:
|
506 |
-
$intype = $decoded['type'];
|
507 |
-
if (isset($decoded['constant']) || !isset($this->ANYmap[$intype]) || (ord($this->encoded[$decoded['start']]) & 0x20)) {
|
508 |
-
return new Element(substr($this->encoded, $decoded['start'], $decoded['length']));
|
509 |
-
}
|
510 |
-
$inmap = $this->ANYmap[$intype];
|
511 |
-
if (is_string($inmap)) {
|
512 |
-
return array($inmap => $this->asn1map($decoded, array('type' => $intype) + $mapping, $special));
|
513 |
-
}
|
514 |
-
break;
|
515 |
-
case $mapping['type'] == self::TYPE_CHOICE:
|
516 |
-
foreach ($mapping['children'] as $key => $option) {
|
517 |
-
switch (true) {
|
518 |
-
case isset($option['constant']) && $option['constant'] == $decoded['constant']:
|
519 |
-
case !isset($option['constant']) && $option['type'] == $decoded['type']:
|
520 |
-
$value = $this->asn1map($decoded, $option, $special);
|
521 |
-
break;
|
522 |
-
case !isset($option['constant']) && $option['type'] == self::TYPE_CHOICE:
|
523 |
-
$v = $this->asn1map($decoded, $option, $special);
|
524 |
-
if (isset($v)) {
|
525 |
-
$value = $v;
|
526 |
-
}
|
527 |
-
}
|
528 |
-
if (isset($value)) {
|
529 |
-
if (isset($special[$key])) {
|
530 |
-
$value = call_user_func($special[$key], $value);
|
531 |
-
}
|
532 |
-
return array($key => $value);
|
533 |
-
}
|
534 |
-
}
|
535 |
-
return null;
|
536 |
-
case isset($mapping['implicit']):
|
537 |
-
case isset($mapping['explicit']):
|
538 |
-
case $decoded['type'] == $mapping['type']:
|
539 |
-
break;
|
540 |
-
default:
|
541 |
-
// if $decoded['type'] and $mapping['type'] are both strings, but different types of strings,
|
542 |
-
// let it through
|
543 |
-
switch (true) {
|
544 |
-
case $decoded['type'] < 18: // self::TYPE_NUMERIC_STRING == 18
|
545 |
-
case $decoded['type'] > 30: // self::TYPE_BMP_STRING == 30
|
546 |
-
case $mapping['type'] < 18:
|
547 |
-
case $mapping['type'] > 30:
|
548 |
-
return null;
|
549 |
-
}
|
550 |
-
}
|
551 |
-
|
552 |
-
if (isset($mapping['implicit'])) {
|
553 |
-
$decoded['type'] = $mapping['type'];
|
554 |
-
}
|
555 |
-
|
556 |
-
switch ($decoded['type']) {
|
557 |
-
case self::TYPE_SEQUENCE:
|
558 |
-
$map = array();
|
559 |
-
|
560 |
-
// ignore the min and max
|
561 |
-
if (isset($mapping['min']) && isset($mapping['max'])) {
|
562 |
-
$child = $mapping['children'];
|
563 |
-
foreach ($decoded['content'] as $content) {
|
564 |
-
if (($map[] = $this->asn1map($content, $child, $special)) === null) {
|
565 |
-
return null;
|
566 |
-
}
|
567 |
-
}
|
568 |
-
|
569 |
-
return $map;
|
570 |
-
}
|
571 |
-
|
572 |
-
$n = count($decoded['content']);
|
573 |
-
$i = 0;
|
574 |
-
|
575 |
-
foreach ($mapping['children'] as $key => $child) {
|
576 |
-
$maymatch = $i < $n; // Match only existing input.
|
577 |
-
if ($maymatch) {
|
578 |
-
$temp = $decoded['content'][$i];
|
579 |
-
|
580 |
-
if ($child['type'] != self::TYPE_CHOICE) {
|
581 |
-
// Get the mapping and input class & constant.
|
582 |
-
$childClass = $tempClass = self::CLASS_UNIVERSAL;
|
583 |
-
$constant = null;
|
584 |
-
if (isset($temp['constant'])) {
|
585 |
-
$tempClass = isset($temp['class']) ? $temp['class'] : self::CLASS_CONTEXT_SPECIFIC;
|
586 |
-
}
|
587 |
-
if (isset($child['class'])) {
|
588 |
-
$childClass = $child['class'];
|
589 |
-
$constant = $child['cast'];
|
590 |
-
} elseif (isset($child['constant'])) {
|
591 |
-
$childClass = self::CLASS_CONTEXT_SPECIFIC;
|
592 |
-
$constant = $child['constant'];
|
593 |
-
}
|
594 |
-
|
595 |
-
if (isset($constant) && isset($temp['constant'])) {
|
596 |
-
// Can only match if constants and class match.
|
597 |
-
$maymatch = $constant == $temp['constant'] && $childClass == $tempClass;
|
598 |
-
} else {
|
599 |
-
// Can only match if no constant expected and type matches or is generic.
|
600 |
-
$maymatch = !isset($child['constant']) && array_search($child['type'], array($temp['type'], self::TYPE_ANY, self::TYPE_CHOICE)) !== false;
|
601 |
-
}
|
602 |
-
}
|
603 |
-
}
|
604 |
-
|
605 |
-
if ($maymatch) {
|
606 |
-
// Attempt submapping.
|
607 |
-
$candidate = $this->asn1map($temp, $child, $special);
|
608 |
-
$maymatch = $candidate !== null;
|
609 |
-
}
|
610 |
-
|
611 |
-
if ($maymatch) {
|
612 |
-
// Got the match: use it.
|
613 |
-
if (isset($special[$key])) {
|
614 |
-
$candidate = call_user_func($special[$key], $candidate);
|
615 |
-
}
|
616 |
-
$map[$key] = $candidate;
|
617 |
-
$i++;
|
618 |
-
} elseif (isset($child['default'])) {
|
619 |
-
$map[$key] = $child['default']; // Use default.
|
620 |
-
} elseif (!isset($child['optional'])) {
|
621 |
-
return null; // Syntax error.
|
622 |
-
}
|
623 |
-
}
|
624 |
-
|
625 |
-
// Fail mapping if all input items have not been consumed.
|
626 |
-
return $i < $n ? null: $map;
|
627 |
-
|
628 |
-
// the main diff between sets and sequences is the encapsulation of the foreach in another for loop
|
629 |
-
case self::TYPE_SET:
|
630 |
-
$map = array();
|
631 |
-
|
632 |
-
// ignore the min and max
|
633 |
-
if (isset($mapping['min']) && isset($mapping['max'])) {
|
634 |
-
$child = $mapping['children'];
|
635 |
-
foreach ($decoded['content'] as $content) {
|
636 |
-
if (($map[] = $this->asn1map($content, $child, $special)) === null) {
|
637 |
-
return null;
|
638 |
-
}
|
639 |
-
}
|
640 |
-
|
641 |
-
return $map;
|
642 |
-
}
|
643 |
-
|
644 |
-
for ($i = 0; $i < count($decoded['content']); $i++) {
|
645 |
-
$temp = $decoded['content'][$i];
|
646 |
-
$tempClass = self::CLASS_UNIVERSAL;
|
647 |
-
if (isset($temp['constant'])) {
|
648 |
-
$tempClass = isset($temp['class']) ? $temp['class'] : self::CLASS_CONTEXT_SPECIFIC;
|
649 |
-
}
|
650 |
-
|
651 |
-
foreach ($mapping['children'] as $key => $child) {
|
652 |
-
if (isset($map[$key])) {
|
653 |
-
continue;
|
654 |
-
}
|
655 |
-
$maymatch = true;
|
656 |
-
if ($child['type'] != self::TYPE_CHOICE) {
|
657 |
-
$childClass = self::CLASS_UNIVERSAL;
|
658 |
-
$constant = null;
|
659 |
-
if (isset($child['class'])) {
|
660 |
-
$childClass = $child['class'];
|
661 |
-
$constant = $child['cast'];
|
662 |
-
} elseif (isset($child['constant'])) {
|
663 |
-
$childClass = self::CLASS_CONTEXT_SPECIFIC;
|
664 |
-
$constant = $child['constant'];
|
665 |
-
}
|
666 |
-
|
667 |
-
if (isset($constant) && isset($temp['constant'])) {
|
668 |
-
// Can only match if constants and class match.
|
669 |
-
$maymatch = $constant == $temp['constant'] && $childClass == $tempClass;
|
670 |
-
} else {
|
671 |
-
// Can only match if no constant expected and type matches or is generic.
|
672 |
-
$maymatch = !isset($child['constant']) && array_search($child['type'], array($temp['type'], self::TYPE_ANY, self::TYPE_CHOICE)) !== false;
|
673 |
-
}
|
674 |
-
}
|
675 |
-
|
676 |
-
if ($maymatch) {
|
677 |
-
// Attempt submapping.
|
678 |
-
$candidate = $this->asn1map($temp, $child, $special);
|
679 |
-
$maymatch = $candidate !== null;
|
680 |
-
}
|
681 |
-
|
682 |
-
if (!$maymatch) {
|
683 |
-
break;
|
684 |
-
}
|
685 |
-
|
686 |
-
// Got the match: use it.
|
687 |
-
if (isset($special[$key])) {
|
688 |
-
$candidate = call_user_func($special[$key], $candidate);
|
689 |
-
}
|
690 |
-
$map[$key] = $candidate;
|
691 |
-
break;
|
692 |
-
}
|
693 |
-
}
|
694 |
-
|
695 |
-
foreach ($mapping['children'] as $key => $child) {
|
696 |
-
if (!isset($map[$key])) {
|
697 |
-
if (isset($child['default'])) {
|
698 |
-
$map[$key] = $child['default'];
|
699 |
-
} elseif (!isset($child['optional'])) {
|
700 |
-
return null;
|
701 |
-
}
|
702 |
-
}
|
703 |
-
}
|
704 |
-
return $map;
|
705 |
-
case self::TYPE_OBJECT_IDENTIFIER:
|
706 |
-
return isset($this->oids[$decoded['content']]) ? $this->oids[$decoded['content']] : $decoded['content'];
|
707 |
-
case self::TYPE_UTC_TIME:
|
708 |
-
case self::TYPE_GENERALIZED_TIME:
|
709 |
-
if (isset($mapping['implicit'])) {
|
710 |
-
$decoded['content'] = $this->_decodeTime($decoded['content'], $decoded['type']);
|
711 |
-
}
|
712 |
-
return $decoded['content'] ? $decoded['content']->format($this->format) : false;
|
713 |
-
case self::TYPE_BIT_STRING:
|
714 |
-
if (isset($mapping['mapping'])) {
|
715 |
-
$offset = ord($decoded['content'][0]);
|
716 |
-
$size = (strlen($decoded['content']) - 1) * 8 - $offset;
|
717 |
-
/*
|
718 |
-
From X.680-0207.pdf#page=46 (21.7):
|
719 |
-
|
720 |
-
"When a "NamedBitList" is used in defining a bitstring type ASN.1 encoding rules are free to add (or remove)
|
721 |
-
arbitrarily any trailing 0 bits to (or from) values that are being encoded or decoded. Application designers should
|
722 |
-
therefore ensure that different semantics are not associated with such values which differ only in the number of trailing
|
723 |
-
0 bits."
|
724 |
-
*/
|
725 |
-
$bits = count($mapping['mapping']) == $size ? array() : array_fill(0, count($mapping['mapping']) - $size, false);
|
726 |
-
for ($i = strlen($decoded['content']) - 1; $i > 0; $i--) {
|
727 |
-
$current = ord($decoded['content'][$i]);
|
728 |
-
for ($j = $offset; $j < 8; $j++) {
|
729 |
-
$bits[] = (bool) ($current & (1 << $j));
|
730 |
-
}
|
731 |
-
$offset = 0;
|
732 |
-
}
|
733 |
-
$values = array();
|
734 |
-
$map = array_reverse($mapping['mapping']);
|
735 |
-
foreach ($map as $i => $value) {
|
736 |
-
if ($bits[$i]) {
|
737 |
-
$values[] = $value;
|
738 |
-
}
|
739 |
-
}
|
740 |
-
return $values;
|
741 |
-
}
|
742 |
-
case self::TYPE_OCTET_STRING:
|
743 |
-
return base64_encode($decoded['content']);
|
744 |
-
case self::TYPE_NULL:
|
745 |
-
return '';
|
746 |
-
case self::TYPE_BOOLEAN:
|
747 |
-
return $decoded['content'];
|
748 |
-
case self::TYPE_NUMERIC_STRING:
|
749 |
-
case self::TYPE_PRINTABLE_STRING:
|
750 |
-
case self::TYPE_TELETEX_STRING:
|
751 |
-
case self::TYPE_VIDEOTEX_STRING:
|
752 |
-
case self::TYPE_IA5_STRING:
|
753 |
-
case self::TYPE_GRAPHIC_STRING:
|
754 |
-
case self::TYPE_VISIBLE_STRING:
|
755 |
-
case self::TYPE_GENERAL_STRING:
|
756 |
-
case self::TYPE_UNIVERSAL_STRING:
|
757 |
-
case self::TYPE_UTF8_STRING:
|
758 |
-
case self::TYPE_BMP_STRING:
|
759 |
-
return $decoded['content'];
|
760 |
-
case self::TYPE_INTEGER:
|
761 |
-
case self::TYPE_ENUMERATED:
|
762 |
-
$temp = $decoded['content'];
|
763 |
-
if (isset($mapping['implicit'])) {
|
764 |
-
$temp = new BigInteger($decoded['content'], -256);
|
765 |
-
}
|
766 |
-
if (isset($mapping['mapping'])) {
|
767 |
-
$temp = (int) $temp->toString();
|
768 |
-
return isset($mapping['mapping'][$temp]) ?
|
769 |
-
$mapping['mapping'][$temp] :
|
770 |
-
false;
|
771 |
-
}
|
772 |
-
return $temp;
|
773 |
-
}
|
774 |
-
}
|
775 |
-
|
776 |
-
/**
|
777 |
-
* ASN.1 Encode
|
778 |
-
*
|
779 |
-
* DER-encodes an ASN.1 semantic mapping ($mapping). Some libraries would probably call this function
|
780 |
-
* an ASN.1 compiler.
|
781 |
-
*
|
782 |
-
* "Special" mappings can be applied via $special.
|
783 |
-
*
|
784 |
-
* @param string $source
|
785 |
-
* @param string $mapping
|
786 |
-
* @param int $idx
|
787 |
-
* @return string
|
788 |
-
* @access public
|
789 |
-
*/
|
790 |
-
function encodeDER($source, $mapping, $special = array())
|
791 |
-
{
|
792 |
-
$this->location = array();
|
793 |
-
return $this->_encode_der($source, $mapping, null, $special);
|
794 |
-
}
|
795 |
-
|
796 |
-
/**
|
797 |
-
* ASN.1 Encode (Helper function)
|
798 |
-
*
|
799 |
-
* @param string $source
|
800 |
-
* @param string $mapping
|
801 |
-
* @param int $idx
|
802 |
-
* @return string
|
803 |
-
* @access private
|
804 |
-
*/
|
805 |
-
function _encode_der($source, $mapping, $idx = null, $special = array())
|
806 |
-
{
|
807 |
-
if ($source instanceof Element) {
|
808 |
-
return $source->element;
|
809 |
-
}
|
810 |
-
|
811 |
-
// do not encode (implicitly optional) fields with value set to default
|
812 |
-
if (isset($mapping['default']) && $source === $mapping['default']) {
|
813 |
-
return '';
|
814 |
-
}
|
815 |
-
|
816 |
-
if (isset($idx)) {
|
817 |
-
if (isset($special[$idx])) {
|
818 |
-
$source = call_user_func($special[$idx], $source);
|
819 |
-
}
|
820 |
-
$this->location[] = $idx;
|
821 |
-
}
|
822 |
-
|
823 |
-
$tag = $mapping['type'];
|
824 |
-
|
825 |
-
switch ($tag) {
|
826 |
-
case self::TYPE_SET: // Children order is not important, thus process in sequence.
|
827 |
-
case self::TYPE_SEQUENCE:
|
828 |
-
$tag|= 0x20; // set the constructed bit
|
829 |
-
|
830 |
-
// ignore the min and max
|
831 |
-
if (isset($mapping['min']) && isset($mapping['max'])) {
|
832 |
-
$value = array();
|
833 |
-
$child = $mapping['children'];
|
834 |
-
|
835 |
-
foreach ($source as $content) {
|
836 |
-
$temp = $this->_encode_der($content, $child, null, $special);
|
837 |
-
if ($temp === false) {
|
838 |
-
return false;
|
839 |
-
}
|
840 |
-
$value[]= $temp;
|
841 |
-
}
|
842 |
-
/* "The encodings of the component values of a set-of value shall appear in ascending order, the encodings being compared
|
843 |
-
as octet strings with the shorter components being padded at their trailing end with 0-octets.
|
844 |
-
NOTE - The padding octets are for comparison purposes only and do not appear in the encodings."
|
845 |
-
|
846 |
-
-- sec 11.6 of http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf */
|
847 |
-
if ($mapping['type'] == self::TYPE_SET) {
|
848 |
-
sort($value);
|
849 |
-
}
|
850 |
-
$value = implode($value, '');
|
851 |
-
break;
|
852 |
-
}
|
853 |
-
|
854 |
-
$value = '';
|
855 |
-
foreach ($mapping['children'] as $key => $child) {
|
856 |
-
if (!array_key_exists($key, $source)) {
|
857 |
-
if (!isset($child['optional'])) {
|
858 |
-
return false;
|
859 |
-
}
|
860 |
-
continue;
|
861 |
-
}
|
862 |
-
|
863 |
-
$temp = $this->_encode_der($source[$key], $child, $key, $special);
|
864 |
-
if ($temp === false) {
|
865 |
-
return false;
|
866 |
-
}
|
867 |
-
|
868 |
-
// An empty child encoding means it has been optimized out.
|
869 |
-
// Else we should have at least one tag byte.
|
870 |
-
if ($temp === '') {
|
871 |
-
continue;
|
872 |
-
}
|
873 |
-
|
874 |
-
// if isset($child['constant']) is true then isset($child['optional']) should be true as well
|
875 |
-
if (isset($child['constant'])) {
|
876 |
-
/*
|
877 |
-
From X.680-0207.pdf#page=58 (30.6):
|
878 |
-
|
879 |
-
"The tagging construction specifies explicit tagging if any of the following holds:
|
880 |
-
...
|
881 |
-
c) the "Tag Type" alternative is used and the value of "TagDefault" for the module is IMPLICIT TAGS or
|
882 |
-
AUTOMATIC TAGS, but the type defined by "Type" is an untagged choice type, an untagged open type, or
|
883 |
-
an untagged "DummyReference" (see ITU-T Rec. X.683 | ISO/IEC 8824-4, 8.3)."
|
884 |
-
*/
|
885 |
-
if (isset($child['explicit']) || $child['type'] == self::TYPE_CHOICE) {
|
886 |
-
$subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | 0x20 | $child['constant']);
|
887 |
-
$temp = $subtag . $this->_encodeLength(strlen($temp)) . $temp;
|
888 |
-
} else {
|
889 |
-
$subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | (ord($temp[0]) & 0x20) | $child['constant']);
|
890 |
-
$temp = $subtag . substr($temp, 1);
|
891 |
-
}
|
892 |
-
}
|
893 |
-
$value.= $temp;
|
894 |
-
}
|
895 |
-
break;
|
896 |
-
case self::TYPE_CHOICE:
|
897 |
-
$temp = false;
|
898 |
-
|
899 |
-
foreach ($mapping['children'] as $key => $child) {
|
900 |
-
if (!isset($source[$key])) {
|
901 |
-
continue;
|
902 |
-
}
|
903 |
-
|
904 |
-
$temp = $this->_encode_der($source[$key], $child, $key, $special);
|
905 |
-
if ($temp === false) {
|
906 |
-
return false;
|
907 |
-
}
|
908 |
-
|
909 |
-
// An empty child encoding means it has been optimized out.
|
910 |
-
// Else we should have at least one tag byte.
|
911 |
-
if ($temp === '') {
|
912 |
-
continue;
|
913 |
-
}
|
914 |
-
|
915 |
-
$tag = ord($temp[0]);
|
916 |
-
|
917 |
-
// if isset($child['constant']) is true then isset($child['optional']) should be true as well
|
918 |
-
if (isset($child['constant'])) {
|
919 |
-
if (isset($child['explicit']) || $child['type'] == self::TYPE_CHOICE) {
|
920 |
-
$subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | 0x20 | $child['constant']);
|
921 |
-
$temp = $subtag . $this->_encodeLength(strlen($temp)) . $temp;
|
922 |
-
} else {
|
923 |
-
$subtag = chr((self::CLASS_CONTEXT_SPECIFIC << 6) | (ord($temp[0]) & 0x20) | $child['constant']);
|
924 |
-
$temp = $subtag . substr($temp, 1);
|
925 |
-
}
|
926 |
-
}
|
927 |
-
}
|
928 |
-
|
929 |
-
if (isset($idx)) {
|
930 |
-
array_pop($this->location);
|
931 |
-
}
|
932 |
-
|
933 |
-
if ($temp && isset($mapping['cast'])) {
|
934 |
-
$temp[0] = chr(($mapping['class'] << 6) | ($tag & 0x20) | $mapping['cast']);
|
935 |
-
}
|
936 |
-
|
937 |
-
return $temp;
|
938 |
-
case self::TYPE_INTEGER:
|
939 |
-
case self::TYPE_ENUMERATED:
|
940 |
-
if (!isset($mapping['mapping'])) {
|
941 |
-
if (is_numeric($source)) {
|
942 |
-
$source = new BigInteger($source);
|
943 |
-
}
|
944 |
-
$value = $source->toBytes(true);
|
945 |
-
} else {
|
946 |
-
$value = array_search($source, $mapping['mapping']);
|
947 |
-
if ($value === false) {
|
948 |
-
return false;
|
949 |
-
}
|
950 |
-
$value = new BigInteger($value);
|
951 |
-
$value = $value->toBytes(true);
|
952 |
-
}
|
953 |
-
if (!strlen($value)) {
|
954 |
-
$value = chr(0);
|
955 |
-
}
|
956 |
-
break;
|
957 |
-
case self::TYPE_UTC_TIME:
|
958 |
-
case self::TYPE_GENERALIZED_TIME:
|
959 |
-
$format = $mapping['type'] == self::TYPE_UTC_TIME ? 'y' : 'Y';
|
960 |
-
$format.= 'mdHis';
|
961 |
-
$date = new DateTime($source, new DateTimeZone('GMT'));
|
962 |
-
$value = $date->format($format) . 'Z';
|
963 |
-
break;
|
964 |
-
case self::TYPE_BIT_STRING:
|
965 |
-
if (isset($mapping['mapping'])) {
|
966 |
-
$bits = array_fill(0, count($mapping['mapping']), 0);
|
967 |
-
$size = 0;
|
968 |
-
for ($i = 0; $i < count($mapping['mapping']); $i++) {
|
969 |
-
if (in_array($mapping['mapping'][$i], $source)) {
|
970 |
-
$bits[$i] = 1;
|
971 |
-
$size = $i;
|
972 |
-
}
|
973 |
-
}
|
974 |
-
|
975 |
-
if (isset($mapping['min']) && $mapping['min'] >= 1 && $size < $mapping['min']) {
|
976 |
-
$size = $mapping['min'] - 1;
|
977 |
-
}
|
978 |
-
|
979 |
-
$offset = 8 - (($size + 1) & 7);
|
980 |
-
$offset = $offset !== 8 ? $offset : 0;
|
981 |
-
|
982 |
-
$value = chr($offset);
|
983 |
-
|
984 |
-
for ($i = $size + 1; $i < count($mapping['mapping']); $i++) {
|
985 |
-
unset($bits[$i]);
|
986 |
-
}
|
987 |
-
|
988 |
-
$bits = implode('', array_pad($bits, $size + $offset + 1, 0));
|
989 |
-
$bytes = explode(' ', rtrim(chunk_split($bits, 8, ' ')));
|
990 |
-
foreach ($bytes as $byte) {
|
991 |
-
$value.= chr(bindec($byte));
|
992 |
-
}
|
993 |
-
|
994 |
-
break;
|
995 |
-
}
|
996 |
-
case self::TYPE_OCTET_STRING:
|
997 |
-
/* The initial octet shall encode, as an unsigned binary integer with bit 1 as the least significant bit,
|
998 |
-
the number of unused bits in the final subsequent octet. The number shall be in the range zero to seven.
|
999 |
-
|
1000 |
-
-- http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=16 */
|
1001 |
-
$value = base64_decode($source);
|
1002 |
-
break;
|
1003 |
-
case self::TYPE_OBJECT_IDENTIFIER:
|
1004 |
-
$oid = preg_match('#(?:\d+\.)+#', $source) ? $source : array_search($source, $this->oids);
|
1005 |
-
if ($oid === false) {
|
1006 |
-
user_error('Invalid OID');
|
1007 |
-
return false;
|
1008 |
-
}
|
1009 |
-
$value = '';
|
1010 |
-
$parts = explode('.', $oid);
|
1011 |
-
$value = chr(40 * $parts[0] + $parts[1]);
|
1012 |
-
for ($i = 2; $i < count($parts); $i++) {
|
1013 |
-
$temp = '';
|
1014 |
-
if (!$parts[$i]) {
|
1015 |
-
$temp = "\0";
|
1016 |
-
} else {
|
1017 |
-
while ($parts[$i]) {
|
1018 |
-
$temp = chr(0x80 | ($parts[$i] & 0x7F)) . $temp;
|
1019 |
-
$parts[$i] >>= 7;
|
1020 |
-
}
|
1021 |
-
$temp[strlen($temp) - 1] = $temp[strlen($temp) - 1] & chr(0x7F);
|
1022 |
-
}
|
1023 |
-
$value.= $temp;
|
1024 |
-
}
|
1025 |
-
break;
|
1026 |
-
case self::TYPE_ANY:
|
1027 |
-
$loc = $this->location;
|
1028 |
-
if (isset($idx)) {
|
1029 |
-
array_pop($this->location);
|
1030 |
-
}
|
1031 |
-
|
1032 |
-
switch (true) {
|
1033 |
-
case !isset($source):
|
1034 |
-
return $this->_encode_der(null, array('type' => self::TYPE_NULL) + $mapping, null, $special);
|
1035 |
-
case is_int($source):
|
1036 |
-
case $source instanceof BigInteger:
|
1037 |
-
return $this->_encode_der($source, array('type' => self::TYPE_INTEGER) + $mapping, null, $special);
|
1038 |
-
case is_float($source):
|
1039 |
-
return $this->_encode_der($source, array('type' => self::TYPE_REAL) + $mapping, null, $special);
|
1040 |
-
case is_bool($source):
|
1041 |
-
return $this->_encode_der($source, array('type' => self::TYPE_BOOLEAN) + $mapping, null, $special);
|
1042 |
-
case is_array($source) && count($source) == 1:
|
1043 |
-
$typename = implode('', array_keys($source));
|
1044 |
-
$outtype = array_search($typename, $this->ANYmap, true);
|
1045 |
-
if ($outtype !== false) {
|
1046 |
-
return $this->_encode_der($source[$typename], array('type' => $outtype) + $mapping, null, $special);
|
1047 |
-
}
|
1048 |
-
}
|
1049 |
-
|
1050 |
-
$filters = $this->filters;
|
1051 |
-
foreach ($loc as $part) {
|
1052 |
-
if (!isset($filters[$part])) {
|
1053 |
-
$filters = false;
|
1054 |
-
break;
|
1055 |
-
}
|
1056 |
-
$filters = $filters[$part];
|
1057 |
-
}
|
1058 |
-
if ($filters === false) {
|
1059 |
-
user_error('No filters defined for ' . implode('/', $loc));
|
1060 |
-
return false;
|
1061 |
-
}
|
1062 |
-
return $this->_encode_der($source, $filters + $mapping, null, $special);
|
1063 |
-
case self::TYPE_NULL:
|
1064 |
-
$value = '';
|
1065 |
-
break;
|
1066 |
-
case self::TYPE_NUMERIC_STRING:
|
1067 |
-
case self::TYPE_TELETEX_STRING:
|
1068 |
-
case self::TYPE_PRINTABLE_STRING:
|
1069 |
-
case self::TYPE_UNIVERSAL_STRING:
|
1070 |
-
case self::TYPE_UTF8_STRING:
|
1071 |
-
case self::TYPE_BMP_STRING:
|
1072 |
-
case self::TYPE_IA5_STRING:
|
1073 |
-
case self::TYPE_VISIBLE_STRING:
|
1074 |
-
case self::TYPE_VIDEOTEX_STRING:
|
1075 |
-
case self::TYPE_GRAPHIC_STRING:
|
1076 |
-
case self::TYPE_GENERAL_STRING:
|
1077 |
-
$value = $source;
|
1078 |
-
break;
|
1079 |
-
case self::TYPE_BOOLEAN:
|
1080 |
-
$value = $source ? "\xFF" : "\x00";
|
1081 |
-
break;
|
1082 |
-
default:
|
1083 |
-
user_error('Mapping provides no type definition for ' . implode('/', $this->location));
|
1084 |
-
return false;
|
1085 |
-
}
|
1086 |
-
|
1087 |
-
if (isset($idx)) {
|
1088 |
-
array_pop($this->location);
|
1089 |
-
}
|
1090 |
-
|
1091 |
-
if (isset($mapping['cast'])) {
|
1092 |
-
if (isset($mapping['explicit']) || $mapping['type'] == self::TYPE_CHOICE) {
|
1093 |
-
$value = chr($tag) . $this->_encodeLength(strlen($value)) . $value;
|
1094 |
-
$tag = ($mapping['class'] << 6) | 0x20 | $mapping['cast'];
|
1095 |
-
} else {
|
1096 |
-
$tag = ($mapping['class'] << 6) | (ord($temp[0]) & 0x20) | $mapping['cast'];
|
1097 |
-
}
|
1098 |
-
}
|
1099 |
-
|
1100 |
-
return chr($tag) . $this->_encodeLength(strlen($value)) . $value;
|
1101 |
-
}
|
1102 |
-
|
1103 |
-
/**
|
1104 |
-
* DER-encode the length
|
1105 |
-
*
|
1106 |
-
* DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See
|
1107 |
-
* {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
|
1108 |
-
*
|
1109 |
-
* @access private
|
1110 |
-
* @param int $length
|
1111 |
-
* @return string
|
1112 |
-
*/
|
1113 |
-
function _encodeLength($length)
|
1114 |
-
{
|
1115 |
-
if ($length <= 0x7F) {
|
1116 |
-
return chr($length);
|
1117 |
-
}
|
1118 |
-
|
1119 |
-
$temp = ltrim(pack('N', $length), chr(0));
|
1120 |
-
return pack('Ca*', 0x80 | strlen($temp), $temp);
|
1121 |
-
}
|
1122 |
-
|
1123 |
-
/**
|
1124 |
-
* BER-decode the time
|
1125 |
-
*
|
1126 |
-
* Called by _decode_ber() and in the case of implicit tags asn1map().
|
1127 |
-
*
|
1128 |
-
* @access private
|
1129 |
-
* @param string $content
|
1130 |
-
* @param int $tag
|
1131 |
-
* @return string
|
1132 |
-
*/
|
1133 |
-
function _decodeTime($content, $tag)
|
1134 |
-
{
|
1135 |
-
/* UTCTime:
|
1136 |
-
http://tools.ietf.org/html/rfc5280#section-4.1.2.5.1
|
1137 |
-
http://www.obj-sys.com/asn1tutorial/node15.html
|
1138 |
-
|
1139 |
-
GeneralizedTime:
|
1140 |
-
http://tools.ietf.org/html/rfc5280#section-4.1.2.5.2
|
1141 |
-
http://www.obj-sys.com/asn1tutorial/node14.html */
|
1142 |
-
|
1143 |
-
$format = 'YmdHis';
|
1144 |
-
|
1145 |
-
if ($tag == self::TYPE_UTC_TIME) {
|
1146 |
-
// https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=28 says "the seconds
|
1147 |
-
// element shall always be present" but none-the-less I've seen X509 certs where it isn't and if the
|
1148 |
-
// browsers parse it phpseclib ought to too
|
1149 |
-
if (preg_match('#^(\d{10})(Z|[+-]\d{4})$#', $content, $matches)) {
|
1150 |
-
$content = $matches[1] . '00' . $matches[2];
|
1151 |
-
}
|
1152 |
-
$prefix = substr($content, 0, 2) >= 50 ? '19' : '20';
|
1153 |
-
$content = $prefix . $content;
|
1154 |
-
} elseif (strpos($content, '.') !== false) {
|
1155 |
-
$format.= '.u';
|
1156 |
-
}
|
1157 |
-
|
1158 |
-
if ($content[strlen($content) - 1] == 'Z') {
|
1159 |
-
$content = substr($content, 0, -1) . '+0000';
|
1160 |
-
}
|
1161 |
-
|
1162 |
-
if (strpos($content, '-') !== false || strpos($content, '+') !== false) {
|
1163 |
-
$format.= 'O';
|
1164 |
-
}
|
1165 |
-
|
1166 |
-
// error supression isn't necessary as of PHP 7.0:
|
1167 |
-
// http://php.net/manual/en/migration70.other-changes.php
|
1168 |
-
return @DateTime::createFromFormat($format, $content);
|
1169 |
-
}
|
1170 |
-
|
1171 |
-
/**
|
1172 |
-
* Set the time format
|
1173 |
-
*
|
1174 |
-
* Sets the time / date format for asn1map().
|
1175 |
-
*
|
1176 |
-
* @access public
|
1177 |
-
* @param string $format
|
1178 |
-
*/
|
1179 |
-
function setTimeFormat($format)
|
1180 |
-
{
|
1181 |
-
$this->format = $format;
|
1182 |
-
}
|
1183 |
-
|
1184 |
-
/**
|
1185 |
-
* Load OIDs
|
1186 |
-
*
|
1187 |
-
* Load the relevant OIDs for a particular ASN.1 semantic mapping.
|
1188 |
-
*
|
1189 |
-
* @access public
|
1190 |
-
* @param array $oids
|
1191 |
-
*/
|
1192 |
-
function loadOIDs($oids)
|
1193 |
-
{
|
1194 |
-
$this->oids = $oids;
|
1195 |
-
}
|
1196 |
-
|
1197 |
-
/**
|
1198 |
-
* Load filters
|
1199 |
-
*
|
1200 |
-
* See \phpseclib\File\X509, etc, for an example.
|
1201 |
-
*
|
1202 |
-
* @access public
|
1203 |
-
* @param array $filters
|
1204 |
-
*/
|
1205 |
-
function loadFilters($filters)
|
1206 |
-
{
|
1207 |
-
$this->filters = $filters;
|
1208 |
-
}
|
1209 |
-
|
1210 |
-
/**
|
1211 |
-
* String Shift
|
1212 |
-
*
|
1213 |
-
* Inspired by array_shift
|
1214 |
-
*
|
1215 |
-
* @param string $string
|
1216 |
-
* @param int $index
|
1217 |
-
* @return string
|
1218 |
-
* @access private
|
1219 |
-
*/
|
1220 |
-
function _string_shift(&$string, $index = 1)
|
1221 |
-
{
|
1222 |
-
$substr = substr($string, 0, $index);
|
1223 |
-
$string = substr($string, $index);
|
1224 |
-
return $substr;
|
1225 |
-
}
|
1226 |
-
|
1227 |
-
/**
|
1228 |
-
* String type conversion
|
1229 |
-
*
|
1230 |
-
* This is a lazy conversion, dealing only with character size.
|
1231 |
-
* No real conversion table is used.
|
1232 |
-
*
|
1233 |
-
* @param string $in
|
1234 |
-
* @param int $from
|
1235 |
-
* @param int $to
|
1236 |
-
* @return string
|
1237 |
-
* @access public
|
1238 |
-
*/
|
1239 |
-
function convert($in, $from = self::TYPE_UTF8_STRING, $to = self::TYPE_UTF8_STRING)
|
1240 |
-
{
|
1241 |
-
if (!isset($this->stringTypeSize[$from]) || !isset($this->stringTypeSize[$to])) {
|
1242 |
-
return false;
|
1243 |
-
}
|
1244 |
-
$insize = $this->stringTypeSize[$from];
|
1245 |
-
$outsize = $this->stringTypeSize[$to];
|
1246 |
-
$inlength = strlen($in);
|
1247 |
-
$out = '';
|
1248 |
-
|
1249 |
-
for ($i = 0; $i < $inlength;) {
|
1250 |
-
if ($inlength - $i < $insize) {
|
1251 |
-
return false;
|
1252 |
-
}
|
1253 |
-
|
1254 |
-
// Get an input character as a 32-bit value.
|
1255 |
-
$c = ord($in[$i++]);
|
1256 |
-
switch (true) {
|
1257 |
-
case $insize == 4:
|
1258 |
-
$c = ($c << 8) | ord($in[$i++]);
|
1259 |
-
$c = ($c << 8) | ord($in[$i++]);
|
1260 |
-
case $insize == 2:
|
1261 |
-
$c = ($c << 8) | ord($in[$i++]);
|
1262 |
-
case $insize == 1:
|
1263 |
-
break;
|
1264 |
-
case ($c & 0x80) == 0x00:
|
1265 |
-
break;
|
1266 |
-
case ($c & 0x40) == 0x00:
|
1267 |
-
return false;
|
1268 |
-
default:
|
1269 |
-
$bit = 6;
|
1270 |
-
do {
|
1271 |
-
if ($bit > 25 || $i >= $inlength || (ord($in[$i]) & 0xC0) != 0x80) {
|
1272 |
-
return false;
|
1273 |
-
}
|
1274 |
-
$c = ($c << 6) | (ord($in[$i++]) & 0x3F);
|
1275 |
-
$bit += 5;
|
1276 |
-
$mask = 1 << $bit;
|
1277 |
-
} while ($c & $bit);
|
1278 |
-
$c &= $mask - 1;
|
1279 |
-
break;
|
1280 |
-
}
|
1281 |
-
|
1282 |
-
// Convert and append the character to output string.
|
1283 |
-
$v = '';
|
1284 |
-
switch (true) {
|
1285 |
-
case $outsize == 4:
|
1286 |
-
$v .= chr($c & 0xFF);
|
1287 |
-
$c >>= 8;
|
1288 |
-
$v .= chr($c & 0xFF);
|
1289 |
-
$c >>= 8;
|
1290 |
-
case $outsize == 2:
|
1291 |
-
$v .= chr($c & 0xFF);
|
1292 |
-
$c >>= 8;
|
1293 |
-
case $outsize == 1:
|
1294 |
-
$v .= chr($c & 0xFF);
|
1295 |
-
$c >>= 8;
|
1296 |
-
if ($c) {
|
1297 |
-
return false;
|
1298 |
-
}
|
1299 |
-
break;
|
1300 |
-
case ($c & 0x80000000) != 0:
|
1301 |
-
return false;
|
1302 |
-
case $c >= 0x04000000:
|
1303 |
-
$v .= chr(0x80 | ($c & 0x3F));
|
1304 |
-
$c = ($c >> 6) | 0x04000000;
|
1305 |
-
case $c >= 0x00200000:
|
1306 |
-
$v .= chr(0x80 | ($c & 0x3F));
|
1307 |
-
$c = ($c >> 6) | 0x00200000;
|
1308 |
-
case $c >= 0x00010000:
|
1309 |
-
$v .= chr(0x80 | ($c & 0x3F));
|
1310 |
-
$c = ($c >> 6) | 0x00010000;
|
1311 |
-
case $c >= 0x00000800:
|
1312 |
-
$v .= chr(0x80 | ($c & 0x3F));
|
1313 |
-
$c = ($c >> 6) | 0x00000800;
|
1314 |
-
case $c >= 0x00000080:
|
1315 |
-
$v .= chr(0x80 | ($c & 0x3F));
|
1316 |
-
$c = ($c >> 6) | 0x000000C0;
|
1317 |
-
default:
|
1318 |
-
$v .= chr($c);
|
1319 |
-
break;
|
1320 |
-
}
|
1321 |
-
$out .= strrev($v);
|
1322 |
-
}
|
1323 |
-
return $out;
|
1324 |
-
}
|
1325 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Element.php
DELETED
@@ -1,47 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Pure-PHP ASN.1 Parser
|
4 |
-
*
|
5 |
-
* PHP version 5
|
6 |
-
*
|
7 |
-
* @category File
|
8 |
-
* @package ASN1
|
9 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
10 |
-
* @copyright 2012 Jim Wigginton
|
11 |
-
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
12 |
-
* @link http://phpseclib.sourceforge.net
|
13 |
-
*/
|
14 |
-
|
15 |
-
namespace phpseclib\File\ASN1;
|
16 |
-
|
17 |
-
/**
|
18 |
-
* ASN.1 Element
|
19 |
-
*
|
20 |
-
* Bypass normal encoding rules in phpseclib\File\ASN1::encodeDER()
|
21 |
-
*
|
22 |
-
* @package ASN1
|
23 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
24 |
-
* @access public
|
25 |
-
*/
|
26 |
-
class Element
|
27 |
-
{
|
28 |
-
/**
|
29 |
-
* Raw element value
|
30 |
-
*
|
31 |
-
* @var string
|
32 |
-
* @access private
|
33 |
-
*/
|
34 |
-
var $element;
|
35 |
-
|
36 |
-
/**
|
37 |
-
* Constructor
|
38 |
-
*
|
39 |
-
* @param string $encoded
|
40 |
-
* @return \phpseclib\File\ASN1\Element
|
41 |
-
* @access public
|
42 |
-
*/
|
43 |
-
function __construct($encoded)
|
44 |
-
{
|
45 |
-
$this->element = $encoded;
|
46 |
-
}
|
47 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/phpseclib/phpseclib/phpseclib/File/X509.php
DELETED
@@ -1,4846 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Pure-PHP X.509 Parser
|
5 |
-
*
|
6 |
-
* PHP version 5
|
7 |
-
*
|
8 |
-
* Encode and decode X.509 certificates.
|
9 |
-
*
|
10 |
-
* The extensions are from {@link http://tools.ietf.org/html/rfc5280 RFC5280} and
|
11 |
-
* {@link http://web.archive.org/web/19961027104704/http://www3.netscape.com/eng/security/cert-exts.html Netscape Certificate Extensions}.
|
12 |
-
*
|
13 |
-
* Note that loading an X.509 certificate and resaving it may invalidate the signature. The reason being that the signature is based on a
|
14 |
-
* portion of the certificate that contains optional parameters with default values. ie. if the parameter isn't there the default value is
|
15 |
-
* used. Problem is, if the parameter is there and it just so happens to have the default value there are two ways that that parameter can
|
16 |
-
* be encoded. It can be encoded explicitly or left out all together. This would effect the signature value and thus may invalidate the
|
17 |
-
* the certificate all together unless the certificate is re-signed.
|
18 |
-
*
|
19 |
-
* @category File
|
20 |
-
* @package X509
|
21 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
22 |
-
* @copyright 2012 Jim Wigginton
|
23 |
-
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
24 |
-
* @link http://phpseclib.sourceforge.net
|
25 |
-
*/
|
26 |
-
|
27 |
-
namespace phpseclib\File;
|
28 |
-
|
29 |
-
use phpseclib\Crypt\Hash;
|
30 |
-
use phpseclib\Crypt\Random;
|
31 |
-
use phpseclib\Crypt\RSA;
|
32 |
-
use phpseclib\File\ASN1\Element;
|
33 |
-
use phpseclib\Math\BigInteger;
|
34 |
-
use DateTime;
|
35 |
-
use DateTimeZone;
|
36 |
-
|
37 |
-
/**
|
38 |
-
* Pure-PHP X.509 Parser
|
39 |
-
*
|
40 |
-
* @package X509
|
41 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
42 |
-
* @access public
|
43 |
-
*/
|
44 |
-
class X509
|
45 |
-
{
|
46 |
-
/**
|
47 |
-
* Flag to only accept signatures signed by certificate authorities
|
48 |
-
*
|
49 |
-
* Not really used anymore but retained all the same to suppress E_NOTICEs from old installs
|
50 |
-
*
|
51 |
-
* @access public
|
52 |
-
*/
|
53 |
-
const VALIDATE_SIGNATURE_BY_CA = 1;
|
54 |
-
|
55 |
-
/**#@+
|
56 |
-
* @access public
|
57 |
-
* @see \phpseclib\File\X509::getDN()
|
58 |
-
*/
|
59 |
-
/**
|
60 |
-
* Return internal array representation
|
61 |
-
*/
|
62 |
-
const DN_ARRAY = 0;
|
63 |
-
/**
|
64 |
-
* Return string
|
65 |
-
*/
|
66 |
-
const DN_STRING = 1;
|
67 |
-
/**
|
68 |
-
* Return ASN.1 name string
|
69 |
-
*/
|
70 |
-
const DN_ASN1 = 2;
|
71 |
-
/**
|
72 |
-
* Return OpenSSL compatible array
|
73 |
-
*/
|
74 |
-
const DN_OPENSSL = 3;
|
75 |
-
/**
|
76 |
-
* Return canonical ASN.1 RDNs string
|
77 |
-
*/
|
78 |
-
const DN_CANON = 4;
|
79 |
-
/**
|
80 |
-
* Return name hash for file indexing
|
81 |
-
*/
|
82 |
-
const DN_HASH = 5;
|
83 |
-
/**#@-*/
|
84 |
-
|
85 |
-
/**#@+
|
86 |
-
* @access public
|
87 |
-
* @see \phpseclib\File\X509::saveX509()
|
88 |
-
* @see \phpseclib\File\X509::saveCSR()
|
89 |
-
* @see \phpseclib\File\X509::saveCRL()
|
90 |
-
*/
|
91 |
-
/**
|
92 |
-
* Save as PEM
|
93 |
-
*
|
94 |
-
* ie. a base64-encoded PEM with a header and a footer
|
95 |
-
*/
|
96 |
-
const FORMAT_PEM = 0;
|
97 |
-
/**
|
98 |
-
* Save as DER
|
99 |
-
*/
|
100 |
-
const FORMAT_DER = 1;
|
101 |
-
/**
|
102 |
-
* Save as a SPKAC
|
103 |
-
*
|
104 |
-
* Only works on CSRs. Not currently supported.
|
105 |
-
*/
|
106 |
-
const FORMAT_SPKAC = 2;
|
107 |
-
/**
|
108 |
-
* Auto-detect the format
|
109 |
-
*
|
110 |
-
* Used only by the load*() functions
|
111 |
-
*/
|
112 |
-
const FORMAT_AUTO_DETECT = 3;
|
113 |
-
/**#@-*/
|
114 |
-
|
115 |
-
/**
|
116 |
-
* Attribute value disposition.
|
117 |
-
* If disposition is >= 0, this is the index of the target value.
|
118 |
-
*/
|
119 |
-
const ATTR_ALL = -1; // All attribute values (array).
|
120 |
-
const ATTR_APPEND = -2; // Add a value.
|
121 |
-
const ATTR_REPLACE = -3; // Clear first, then add a value.
|
122 |
-
|
123 |
-
/**
|
124 |
-
* ASN.1 syntax for X.509 certificates
|
125 |
-
*
|
126 |
-
* @var array
|
127 |
-
* @access private
|
128 |
-
*/
|
129 |
-
var $Certificate;
|
130 |
-
|
131 |
-
/**#@+
|
132 |
-
* ASN.1 syntax for various extensions
|
133 |
-
*
|
134 |
-
* @access private
|
135 |
-
*/
|
136 |
-
var $DirectoryString;
|
137 |
-
var $PKCS9String;
|
138 |
-
var $AttributeValue;
|
139 |
-
var $Extensions;
|
140 |
-
var $KeyUsage;
|
141 |
-
var $ExtKeyUsageSyntax;
|
142 |
-
var $BasicConstraints;
|
143 |
-
var $KeyIdentifier;
|
144 |
-
var $CRLDistributionPoints;
|
145 |
-
var $AuthorityKeyIdentifier;
|
146 |
-
var $CertificatePolicies;
|
147 |
-
var $AuthorityInfoAccessSyntax;
|
148 |
-
var $SubjectAltName;
|
149 |
-
var $SubjectDirectoryAttributes;
|
150 |
-
var $PrivateKeyUsagePeriod;
|
151 |
-
var $IssuerAltName;
|
152 |
-
var $PolicyMappings;
|
153 |
-
var $NameConstraints;
|
154 |
-
|
155 |
-
var $CPSuri;
|
156 |
-
var $UserNotice;
|
157 |
-
|
158 |
-
var $netscape_cert_type;
|
159 |
-
var $netscape_comment;
|
160 |
-
var $netscape_ca_policy_url;
|
161 |
-
|
162 |
-
var $Name;
|
163 |
-
var $RelativeDistinguishedName;
|
164 |
-
var $CRLNumber;
|
165 |
-
var $CRLReason;
|
166 |
-
var $IssuingDistributionPoint;
|
167 |
-
var $InvalidityDate;
|
168 |
-
var $CertificateIssuer;
|
169 |
-
var $HoldInstructionCode;
|
170 |
-
var $SignedPublicKeyAndChallenge;
|
171 |
-
/**#@-*/
|
172 |
-
|
173 |
-
/**#@+
|
174 |
-
* ASN.1 syntax for various DN attributes
|
175 |
-
*
|
176 |
-
* @access private
|
177 |
-
*/
|
178 |
-
var $PostalAddress;
|
179 |
-
/**#@-*/
|
180 |
-
|
181 |
-
/**
|
182 |
-
* ASN.1 syntax for Certificate Signing Requests (RFC2986)
|
183 |
-
*
|
184 |
-
* @var array
|
185 |
-
* @access private
|
186 |
-
*/
|
187 |
-
var $CertificationRequest;
|
188 |
-
|
189 |
-
/**
|
190 |
-
* ASN.1 syntax for Certificate Revocation Lists (RFC5280)
|
191 |
-
*
|
192 |
-
* @var array
|
193 |
-
* @access private
|
194 |
-
*/
|
195 |
-
var $CertificateList;
|
196 |
-
|
197 |
-
/**
|
198 |
-
* Distinguished Name
|
199 |
-
*
|
200 |
-
* @var array
|
201 |
-
* @access private
|
202 |
-
*/
|
203 |
-
var $dn;
|
204 |
-
|
205 |
-
/**
|
206 |
-
* Public key
|
207 |
-
*
|
208 |
-
* @var string
|
209 |
-
* @access private
|
210 |
-
*/
|
211 |
-
var $publicKey;
|
212 |
-
|
213 |
-
/**
|
214 |
-
* Private key
|
215 |
-
*
|
216 |
-
* @var string
|
217 |
-
* @access private
|
218 |
-
*/
|
219 |
-
var $privateKey;
|
220 |
-
|
221 |
-
/**
|
222 |
-
* Object identifiers for X.509 certificates
|
223 |
-
*
|
224 |
-
* @var array
|
225 |
-
* @access private
|
226 |
-
* @link http://en.wikipedia.org/wiki/Object_identifier
|
227 |
-
*/
|
228 |
-
var $oids;
|
229 |
-
|
230 |
-
/**
|
231 |
-
* The certificate authorities
|
232 |
-
*
|
233 |
-
* @var array
|
234 |
-
* @access private
|
235 |
-
*/
|
236 |
-
var $CAs;
|
237 |
-
|
238 |
-
/**
|
239 |
-
* The currently loaded certificate
|
240 |
-
*
|
241 |
-
* @var array
|
242 |
-
* @access private
|
243 |
-
*/
|
244 |
-
var $currentCert;
|
245 |
-
|
246 |
-
/**
|
247 |
-
* The signature subject
|
248 |
-
*
|
249 |
-
* There's no guarantee \phpseclib\File\X509 is going to re-encode an X.509 cert in the same way it was originally
|
250 |
-
* encoded so we take save the portion of the original cert that the signature would have made for.
|
251 |
-
*
|
252 |
-
* @var string
|
253 |
-
* @access private
|
254 |
-
*/
|
255 |
-
var $signatureSubject;
|
256 |
-
|
257 |
-
/**
|
258 |
-
* Certificate Start Date
|
259 |
-
*
|
260 |
-
* @var string
|
261 |
-
* @access private
|
262 |
-
*/
|
263 |
-
var $startDate;
|
264 |
-
|
265 |
-
/**
|
266 |
-
* Certificate End Date
|
267 |
-
*
|
268 |
-
* @var string
|
269 |
-
* @access private
|
270 |
-
*/
|
271 |
-
var $endDate;
|
272 |
-
|
273 |
-
/**
|
274 |
-
* Serial Number
|
275 |
-
*
|
276 |
-
* @var string
|
277 |
-
* @access private
|
278 |
-
*/
|
279 |
-
var $serialNumber;
|
280 |
-
|
281 |
-
/**
|
282 |
-
* Key Identifier
|
283 |
-
*
|
284 |
-
* See {@link http://tools.ietf.org/html/rfc5280#section-4.2.1.1 RFC5280#section-4.2.1.1} and
|
285 |
-
* {@link http://tools.ietf.org/html/rfc5280#section-4.2.1.2 RFC5280#section-4.2.1.2}.
|
286 |
-
*
|
287 |
-
* @var string
|
288 |
-
* @access private
|
289 |
-
*/
|
290 |
-
var $currentKeyIdentifier;
|
291 |
-
|
292 |
-
/**
|
293 |
-
* CA Flag
|
294 |
-
*
|
295 |
-
* @var bool
|
296 |
-
* @access private
|
297 |
-
*/
|
298 |
-
var $caFlag = false;
|
299 |
-
|
300 |
-
/**
|
301 |
-
* SPKAC Challenge
|
302 |
-
*
|
303 |
-
* @var string
|
304 |
-
* @access private
|
305 |
-
*/
|
306 |
-
var $challenge;
|
307 |
-
|
308 |
-
/**
|
309 |
-
* Default Constructor.
|
310 |
-
*
|
311 |
-
* @return \phpseclib\File\X509
|
312 |
-
* @access public
|
313 |
-
*/
|
314 |
-
function __construct()
|
315 |
-
{
|
316 |
-
// Explicitly Tagged Module, 1988 Syntax
|
317 |
-
// http://tools.ietf.org/html/rfc5280#appendix-A.1
|
318 |
-
|
319 |
-
$this->DirectoryString = array(
|
320 |
-
'type' => ASN1::TYPE_CHOICE,
|
321 |
-
'children' => array(
|
322 |
-
'teletexString' => array('type' => ASN1::TYPE_TELETEX_STRING),
|
323 |
-
'printableString' => array('type' => ASN1::TYPE_PRINTABLE_STRING),
|
324 |
-
'universalString' => array('type' => ASN1::TYPE_UNIVERSAL_STRING),
|
325 |
-
'utf8String' => array('type' => ASN1::TYPE_UTF8_STRING),
|
326 |
-
'bmpString' => array('type' => ASN1::TYPE_BMP_STRING)
|
327 |
-
)
|
328 |
-
);
|
329 |
-
|
330 |
-
$this->PKCS9String = array(
|
331 |
-
'type' => ASN1::TYPE_CHOICE,
|
332 |
-
'children' => array(
|
333 |
-
'ia5String' => array('type' => ASN1::TYPE_IA5_STRING),
|
334 |
-
'directoryString' => $this->DirectoryString
|
335 |
-
)
|
336 |
-
);
|
337 |
-
|
338 |
-
$this->AttributeValue = array('type' => ASN1::TYPE_ANY);
|
339 |
-
|
340 |
-
$AttributeType = array('type' => ASN1::TYPE_OBJECT_IDENTIFIER);
|
341 |
-
|
342 |
-
$AttributeTypeAndValue = array(
|
343 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
344 |
-
'children' => array(
|
345 |
-
'type' => $AttributeType,
|
346 |
-
'value'=> $this->AttributeValue
|
347 |
-
)
|
348 |
-
);
|
349 |
-
|
350 |
-
/*
|
351 |
-
In practice, RDNs containing multiple name-value pairs (called "multivalued RDNs") are rare,
|
352 |
-
but they can be useful at times when either there is no unique attribute in the entry or you
|
353 |
-
want to ensure that the entry's DN contains some useful identifying information.
|
354 |
-
|
355 |
-
- https://www.opends.org/wiki/page/DefinitionRelativeDistinguishedName
|
356 |
-
*/
|
357 |
-
$this->RelativeDistinguishedName = array(
|
358 |
-
'type' => ASN1::TYPE_SET,
|
359 |
-
'min' => 1,
|
360 |
-
'max' => -1,
|
361 |
-
'children' => $AttributeTypeAndValue
|
362 |
-
);
|
363 |
-
|
364 |
-
// http://tools.ietf.org/html/rfc5280#section-4.1.2.4
|
365 |
-
$RDNSequence = array(
|
366 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
367 |
-
// RDNSequence does not define a min or a max, which means it doesn't have one
|
368 |
-
'min' => 0,
|
369 |
-
'max' => -1,
|
370 |
-
'children' => $this->RelativeDistinguishedName
|
371 |
-
);
|
372 |
-
|
373 |
-
$this->Name = array(
|
374 |
-
'type' => ASN1::TYPE_CHOICE,
|
375 |
-
'children' => array(
|
376 |
-
'rdnSequence' => $RDNSequence
|
377 |
-
)
|
378 |
-
);
|
379 |
-
|
380 |
-
// http://tools.ietf.org/html/rfc5280#section-4.1.1.2
|
381 |
-
$AlgorithmIdentifier = array(
|
382 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
383 |
-
'children' => array(
|
384 |
-
'algorithm' => array('type' => ASN1::TYPE_OBJECT_IDENTIFIER),
|
385 |
-
'parameters' => array(
|
386 |
-
'type' => ASN1::TYPE_ANY,
|
387 |
-
'optional' => true
|
388 |
-
)
|
389 |
-
)
|
390 |
-
);
|
391 |
-
|
392 |
-
/*
|
393 |
-
A certificate using system MUST reject the certificate if it encounters
|
394 |
-
a critical extension it does not recognize; however, a non-critical
|
395 |
-
extension may be ignored if it is not recognized.
|
396 |
-
|
397 |
-
http://tools.ietf.org/html/rfc5280#section-4.2
|
398 |
-
*/
|
399 |
-
$Extension = array(
|
400 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
401 |
-
'children' => array(
|
402 |
-
'extnId' => array('type' => ASN1::TYPE_OBJECT_IDENTIFIER),
|
403 |
-
'critical' => array(
|
404 |
-
'type' => ASN1::TYPE_BOOLEAN,
|
405 |
-
'optional' => true,
|
406 |
-
'default' => false
|
407 |
-
),
|
408 |
-
'extnValue' => array('type' => ASN1::TYPE_OCTET_STRING)
|
409 |
-
)
|
410 |
-
);
|
411 |
-
|
412 |
-
$this->Extensions = array(
|
413 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
414 |
-
'min' => 1,
|
415 |
-
// technically, it's MAX, but we'll assume anything < 0 is MAX
|
416 |
-
'max' => -1,
|
417 |
-
// if 'children' isn't an array then 'min' and 'max' must be defined
|
418 |
-
'children' => $Extension
|
419 |
-
);
|
420 |
-
|
421 |
-
$SubjectPublicKeyInfo = array(
|
422 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
423 |
-
'children' => array(
|
424 |
-
'algorithm' => $AlgorithmIdentifier,
|
425 |
-
'subjectPublicKey' => array('type' => ASN1::TYPE_BIT_STRING)
|
426 |
-
)
|
427 |
-
);
|
428 |
-
|
429 |
-
$UniqueIdentifier = array('type' => ASN1::TYPE_BIT_STRING);
|
430 |
-
|
431 |
-
$Time = array(
|
432 |
-
'type' => ASN1::TYPE_CHOICE,
|
433 |
-
'children' => array(
|
434 |
-
'utcTime' => array('type' => ASN1::TYPE_UTC_TIME),
|
435 |
-
'generalTime' => array('type' => ASN1::TYPE_GENERALIZED_TIME)
|
436 |
-
)
|
437 |
-
);
|
438 |
-
|
439 |
-
// http://tools.ietf.org/html/rfc5280#section-4.1.2.5
|
440 |
-
$Validity = array(
|
441 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
442 |
-
'children' => array(
|
443 |
-
'notBefore' => $Time,
|
444 |
-
'notAfter' => $Time
|
445 |
-
)
|
446 |
-
);
|
447 |
-
|
448 |
-
$CertificateSerialNumber = array('type' => ASN1::TYPE_INTEGER);
|
449 |
-
|
450 |
-
$Version = array(
|
451 |
-
'type' => ASN1::TYPE_INTEGER,
|
452 |
-
'mapping' => array('v1', 'v2', 'v3')
|
453 |
-
);
|
454 |
-
|
455 |
-
// assert($TBSCertificate['children']['signature'] == $Certificate['children']['signatureAlgorithm'])
|
456 |
-
$TBSCertificate = array(
|
457 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
458 |
-
'children' => array(
|
459 |
-
// technically, default implies optional, but we'll define it as being optional, none-the-less, just to
|
460 |
-
// reenforce that fact
|
461 |
-
'version' => array(
|
462 |
-
'constant' => 0,
|
463 |
-
'optional' => true,
|
464 |
-
'explicit' => true,
|
465 |
-
'default' => 'v1'
|
466 |
-
) + $Version,
|
467 |
-
'serialNumber' => $CertificateSerialNumber,
|
468 |
-
'signature' => $AlgorithmIdentifier,
|
469 |
-
'issuer' => $this->Name,
|
470 |
-
'validity' => $Validity,
|
471 |
-
'subject' => $this->Name,
|
472 |
-
'subjectPublicKeyInfo' => $SubjectPublicKeyInfo,
|
473 |
-
// implicit means that the T in the TLV structure is to be rewritten, regardless of the type
|
474 |
-
'issuerUniqueID' => array(
|
475 |
-
'constant' => 1,
|
476 |
-
'optional' => true,
|
477 |
-
'implicit' => true
|
478 |
-
) + $UniqueIdentifier,
|
479 |
-
'subjectUniqueID' => array(
|
480 |
-
'constant' => 2,
|
481 |
-
'optional' => true,
|
482 |
-
'implicit' => true
|
483 |
-
) + $UniqueIdentifier,
|
484 |
-
// <http://tools.ietf.org/html/rfc2459#page-74> doesn't use the EXPLICIT keyword but if
|
485 |
-
// it's not IMPLICIT, it's EXPLICIT
|
486 |
-
'extensions' => array(
|
487 |
-
'constant' => 3,
|
488 |
-
'optional' => true,
|
489 |
-
'explicit' => true
|
490 |
-
) + $this->Extensions
|
491 |
-
)
|
492 |
-
);
|
493 |
-
|
494 |
-
$this->Certificate = array(
|
495 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
496 |
-
'children' => array(
|
497 |
-
'tbsCertificate' => $TBSCertificate,
|
498 |
-
'signatureAlgorithm' => $AlgorithmIdentifier,
|
499 |
-
'signature' => array('type' => ASN1::TYPE_BIT_STRING)
|
500 |
-
)
|
501 |
-
);
|
502 |
-
|
503 |
-
$this->KeyUsage = array(
|
504 |
-
'type' => ASN1::TYPE_BIT_STRING,
|
505 |
-
'mapping' => array(
|
506 |
-
'digitalSignature',
|
507 |
-
'nonRepudiation',
|
508 |
-
'keyEncipherment',
|
509 |
-
'dataEncipherment',
|
510 |
-
'keyAgreement',
|
511 |
-
'keyCertSign',
|
512 |
-
'cRLSign',
|
513 |
-
'encipherOnly',
|
514 |
-
'decipherOnly'
|
515 |
-
)
|
516 |
-
);
|
517 |
-
|
518 |
-
$this->BasicConstraints = array(
|
519 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
520 |
-
'children' => array(
|
521 |
-
'cA' => array(
|
522 |
-
'type' => ASN1::TYPE_BOOLEAN,
|
523 |
-
'optional' => true,
|
524 |
-
'default' => false
|
525 |
-
),
|
526 |
-
'pathLenConstraint' => array(
|
527 |
-
'type' => ASN1::TYPE_INTEGER,
|
528 |
-
'optional' => true
|
529 |
-
)
|
530 |
-
)
|
531 |
-
);
|
532 |
-
|
533 |
-
$this->KeyIdentifier = array('type' => ASN1::TYPE_OCTET_STRING);
|
534 |
-
|
535 |
-
$OrganizationalUnitNames = array(
|
536 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
537 |
-
'min' => 1,
|
538 |
-
'max' => 4, // ub-organizational-units
|
539 |
-
'children' => array('type' => ASN1::TYPE_PRINTABLE_STRING)
|
540 |
-
);
|
541 |
-
|
542 |
-
$PersonalName = array(
|
543 |
-
'type' => ASN1::TYPE_SET,
|
544 |
-
'children' => array(
|
545 |
-
'surname' => array(
|
546 |
-
'type' => ASN1::TYPE_PRINTABLE_STRING,
|
547 |
-
'constant' => 0,
|
548 |
-
'optional' => true,
|
549 |
-
'implicit' => true
|
550 |
-
),
|
551 |
-
'given-name' => array(
|
552 |
-
'type' => ASN1::TYPE_PRINTABLE_STRING,
|
553 |
-
'constant' => 1,
|
554 |
-
'optional' => true,
|
555 |
-
'implicit' => true
|
556 |
-
),
|
557 |
-
'initials' => array(
|
558 |
-
'type' => ASN1::TYPE_PRINTABLE_STRING,
|
559 |
-
'constant' => 2,
|
560 |
-
'optional' => true,
|
561 |
-
'implicit' => true
|
562 |
-
),
|
563 |
-
'generation-qualifier' => array(
|
564 |
-
'type' => ASN1::TYPE_PRINTABLE_STRING,
|
565 |
-
'constant' => 3,
|
566 |
-
'optional' => true,
|
567 |
-
'implicit' => true
|
568 |
-
)
|
569 |
-
)
|
570 |
-
);
|
571 |
-
|
572 |
-
$NumericUserIdentifier = array('type' => ASN1::TYPE_NUMERIC_STRING);
|
573 |
-
|
574 |
-
$OrganizationName = array('type' => ASN1::TYPE_PRINTABLE_STRING);
|
575 |
-
|
576 |
-
$PrivateDomainName = array(
|
577 |
-
'type' => ASN1::TYPE_CHOICE,
|
578 |
-
'children' => array(
|
579 |
-
'numeric' => array('type' => ASN1::TYPE_NUMERIC_STRING),
|
580 |
-
'printable' => array('type' => ASN1::TYPE_PRINTABLE_STRING)
|
581 |
-
)
|
582 |
-
);
|
583 |
-
|
584 |
-
$TerminalIdentifier = array('type' => ASN1::TYPE_PRINTABLE_STRING);
|
585 |
-
|
586 |
-
$NetworkAddress = array('type' => ASN1::TYPE_NUMERIC_STRING);
|
587 |
-
|
588 |
-
$AdministrationDomainName = array(
|
589 |
-
'type' => ASN1::TYPE_CHOICE,
|
590 |
-
// if class isn't present it's assumed to be \phpseclib\File\ASN1::CLASS_UNIVERSAL or
|
591 |
-
// (if constant is present) \phpseclib\File\ASN1::CLASS_CONTEXT_SPECIFIC
|
592 |
-
'class' => ASN1::CLASS_APPLICATION,
|
593 |
-
'cast' => 2,
|
594 |
-
'children' => array(
|
595 |
-
'numeric' => array('type' => ASN1::TYPE_NUMERIC_STRING),
|
596 |
-
'printable' => array('type' => ASN1::TYPE_PRINTABLE_STRING)
|
597 |
-
)
|
598 |
-
);
|
599 |
-
|
600 |
-
$CountryName = array(
|
601 |
-
'type' => ASN1::TYPE_CHOICE,
|
602 |
-
// if class isn't present it's assumed to be \phpseclib\File\ASN1::CLASS_UNIVERSAL or
|
603 |
-
// (if constant is present) \phpseclib\File\ASN1::CLASS_CONTEXT_SPECIFIC
|
604 |
-
'class' => ASN1::CLASS_APPLICATION,
|
605 |
-
'cast' => 1,
|
606 |
-
'children' => array(
|
607 |
-
'x121-dcc-code' => array('type' => ASN1::TYPE_NUMERIC_STRING),
|
608 |
-
'iso-3166-alpha2-code' => array('type' => ASN1::TYPE_PRINTABLE_STRING)
|
609 |
-
)
|
610 |
-
);
|
611 |
-
|
612 |
-
$AnotherName = array(
|
613 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
614 |
-
'children' => array(
|
615 |
-
'type-id' => array('type' => ASN1::TYPE_OBJECT_IDENTIFIER),
|
616 |
-
'value' => array(
|
617 |
-
'type' => ASN1::TYPE_ANY,
|
618 |
-
'constant' => 0,
|
619 |
-
'optional' => true,
|
620 |
-
'explicit' => true
|
621 |
-
)
|
622 |
-
)
|
623 |
-
);
|
624 |
-
|
625 |
-
$ExtensionAttribute = array(
|
626 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
627 |
-
'children' => array(
|
628 |
-
'extension-attribute-type' => array(
|
629 |
-
'type' => ASN1::TYPE_PRINTABLE_STRING,
|
630 |
-
'constant' => 0,
|
631 |
-
'optional' => true,
|
632 |
-
'implicit' => true
|
633 |
-
),
|
634 |
-
'extension-attribute-value' => array(
|
635 |
-
'type' => ASN1::TYPE_ANY,
|
636 |
-
'constant' => 1,
|
637 |
-
'optional' => true,
|
638 |
-
'explicit' => true
|
639 |
-
)
|
640 |
-
)
|
641 |
-
);
|
642 |
-
|
643 |
-
$ExtensionAttributes = array(
|
644 |
-
'type' => ASN1::TYPE_SET,
|
645 |
-
'min' => 1,
|
646 |
-
'max' => 256, // ub-extension-attributes
|
647 |
-
'children' => $ExtensionAttribute
|
648 |
-
);
|
649 |
-
|
650 |
-
$BuiltInDomainDefinedAttribute = array(
|
651 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
652 |
-
'children' => array(
|
653 |
-
'type' => array('type' => ASN1::TYPE_PRINTABLE_STRING),
|
654 |
-
'value' => array('type' => ASN1::TYPE_PRINTABLE_STRING)
|
655 |
-
)
|
656 |
-
);
|
657 |
-
|
658 |
-
$BuiltInDomainDefinedAttributes = array(
|
659 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
660 |
-
'min' => 1,
|
661 |
-
'max' => 4, // ub-domain-defined-attributes
|
662 |
-
'children' => $BuiltInDomainDefinedAttribute
|
663 |
-
);
|
664 |
-
|
665 |
-
$BuiltInStandardAttributes = array(
|
666 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
667 |
-
'children' => array(
|
668 |
-
'country-name' => array('optional' => true) + $CountryName,
|
669 |
-
'administration-domain-name' => array('optional' => true) + $AdministrationDomainName,
|
670 |
-
'network-address' => array(
|
671 |
-
'constant' => 0,
|
672 |
-
'optional' => true,
|
673 |
-
'implicit' => true
|
674 |
-
) + $NetworkAddress,
|
675 |
-
'terminal-identifier' => array(
|
676 |
-
'constant' => 1,
|
677 |
-
'optional' => true,
|
678 |
-
'implicit' => true
|
679 |
-
) + $TerminalIdentifier,
|
680 |
-
'private-domain-name' => array(
|
681 |
-
'constant' => 2,
|
682 |
-
'optional' => true,
|
683 |
-
'explicit' => true
|
684 |
-
) + $PrivateDomainName,
|
685 |
-
'organization-name' => array(
|
686 |
-
'constant' => 3,
|
687 |
-
'optional' => true,
|
688 |
-
'implicit' => true
|
689 |
-
) + $OrganizationName,
|
690 |
-
'numeric-user-identifier' => array(
|
691 |
-
'constant' => 4,
|
692 |
-
'optional' => true,
|
693 |
-
'implicit' => true
|
694 |
-
) + $NumericUserIdentifier,
|
695 |
-
'personal-name' => array(
|
696 |
-
'constant' => 5,
|
697 |
-
'optional' => true,
|
698 |
-
'implicit' => true
|
699 |
-
) + $PersonalName,
|
700 |
-
'organizational-unit-names' => array(
|
701 |
-
'constant' => 6,
|
702 |
-
'optional' => true,
|
703 |
-
'implicit' => true
|
704 |
-
) + $OrganizationalUnitNames
|
705 |
-
)
|
706 |
-
);
|
707 |
-
|
708 |
-
$ORAddress = array(
|
709 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
710 |
-
'children' => array(
|
711 |
-
'built-in-standard-attributes' => $BuiltInStandardAttributes,
|
712 |
-
'built-in-domain-defined-attributes' => array('optional' => true) + $BuiltInDomainDefinedAttributes,
|
713 |
-
'extension-attributes' => array('optional' => true) + $ExtensionAttributes
|
714 |
-
)
|
715 |
-
);
|
716 |
-
|
717 |
-
$EDIPartyName = array(
|
718 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
719 |
-
'children' => array(
|
720 |
-
'nameAssigner' => array(
|
721 |
-
'constant' => 0,
|
722 |
-
'optional' => true,
|
723 |
-
'implicit' => true
|
724 |
-
) + $this->DirectoryString,
|
725 |
-
// partyName is technically required but \phpseclib\File\ASN1 doesn't currently support non-optional constants and
|
726 |
-
// setting it to optional gets the job done in any event.
|
727 |
-
'partyName' => array(
|
728 |
-
'constant' => 1,
|
729 |
-
'optional' => true,
|
730 |
-
'implicit' => true
|
731 |
-
) + $this->DirectoryString
|
732 |
-
)
|
733 |
-
);
|
734 |
-
|
735 |
-
$GeneralName = array(
|
736 |
-
'type' => ASN1::TYPE_CHOICE,
|
737 |
-
'children' => array(
|
738 |
-
'otherName' => array(
|
739 |
-
'constant' => 0,
|
740 |
-
'optional' => true,
|
741 |
-
'implicit' => true
|
742 |
-
) + $AnotherName,
|
743 |
-
'rfc822Name' => array(
|
744 |
-
'type' => ASN1::TYPE_IA5_STRING,
|
745 |
-
'constant' => 1,
|
746 |
-
'optional' => true,
|
747 |
-
'implicit' => true
|
748 |
-
),
|
749 |
-
'dNSName' => array(
|
750 |
-
'type' => ASN1::TYPE_IA5_STRING,
|
751 |
-
'constant' => 2,
|
752 |
-
'optional' => true,
|
753 |
-
'implicit' => true
|
754 |
-
),
|
755 |
-
'x400Address' => array(
|
756 |
-
'constant' => 3,
|
757 |
-
'optional' => true,
|
758 |
-
'implicit' => true
|
759 |
-
) + $ORAddress,
|
760 |
-
'directoryName' => array(
|
761 |
-
'constant' => 4,
|
762 |
-
'optional' => true,
|
763 |
-
'explicit' => true
|
764 |
-
) + $this->Name,
|
765 |
-
'ediPartyName' => array(
|
766 |
-
'constant' => 5,
|
767 |
-
'optional' => true,
|
768 |
-
'implicit' => true
|
769 |
-
) + $EDIPartyName,
|
770 |
-
'uniformResourceIdentifier' => array(
|
771 |
-
'type' => ASN1::TYPE_IA5_STRING,
|
772 |
-
'constant' => 6,
|
773 |
-
'optional' => true,
|
774 |
-
'implicit' => true
|
775 |
-
),
|
776 |
-
'iPAddress' => array(
|
777 |
-
'type' => ASN1::TYPE_OCTET_STRING,
|
778 |
-
'constant' => 7,
|
779 |
-
'optional' => true,
|
780 |
-
'implicit' => true
|
781 |
-
),
|
782 |
-
'registeredID' => array(
|
783 |
-
'type' => ASN1::TYPE_OBJECT_IDENTIFIER,
|
784 |
-
'constant' => 8,
|
785 |
-
'optional' => true,
|
786 |
-
'implicit' => true
|
787 |
-
)
|
788 |
-
)
|
789 |
-
);
|
790 |
-
|
791 |
-
$GeneralNames = array(
|
792 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
793 |
-
'min' => 1,
|
794 |
-
'max' => -1,
|
795 |
-
'children' => $GeneralName
|
796 |
-
);
|
797 |
-
|
798 |
-
$this->IssuerAltName = $GeneralNames;
|
799 |
-
|
800 |
-
$ReasonFlags = array(
|
801 |
-
'type' => ASN1::TYPE_BIT_STRING,
|
802 |
-
'mapping' => array(
|
803 |
-
'unused',
|
804 |
-
'keyCompromise',
|
805 |
-
'cACompromise',
|
806 |
-
'affiliationChanged',
|
807 |
-
'superseded',
|
808 |
-
'cessationOfOperation',
|
809 |
-
'certificateHold',
|
810 |
-
'privilegeWithdrawn',
|
811 |
-
'aACompromise'
|
812 |
-
)
|
813 |
-
);
|
814 |
-
|
815 |
-
$DistributionPointName = array(
|
816 |
-
'type' => ASN1::TYPE_CHOICE,
|
817 |
-
'children' => array(
|
818 |
-
'fullName' => array(
|
819 |
-
'constant' => 0,
|
820 |
-
'optional' => true,
|
821 |
-
'implicit' => true
|
822 |
-
) + $GeneralNames,
|
823 |
-
'nameRelativeToCRLIssuer' => array(
|
824 |
-
'constant' => 1,
|
825 |
-
'optional' => true,
|
826 |
-
'implicit' => true
|
827 |
-
) + $this->RelativeDistinguishedName
|
828 |
-
)
|
829 |
-
);
|
830 |
-
|
831 |
-
$DistributionPoint = array(
|
832 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
833 |
-
'children' => array(
|
834 |
-
'distributionPoint' => array(
|
835 |
-
'constant' => 0,
|
836 |
-
'optional' => true,
|
837 |
-
'explicit' => true
|
838 |
-
) + $DistributionPointName,
|
839 |
-
'reasons' => array(
|
840 |
-
'constant' => 1,
|
841 |
-
'optional' => true,
|
842 |
-
'implicit' => true
|
843 |
-
) + $ReasonFlags,
|
844 |
-
'cRLIssuer' => array(
|
845 |
-
'constant' => 2,
|
846 |
-
'optional' => true,
|
847 |
-
'implicit' => true
|
848 |
-
) + $GeneralNames
|
849 |
-
)
|
850 |
-
);
|
851 |
-
|
852 |
-
$this->CRLDistributionPoints = array(
|
853 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
854 |
-
'min' => 1,
|
855 |
-
'max' => -1,
|
856 |
-
'children' => $DistributionPoint
|
857 |
-
);
|
858 |
-
|
859 |
-
$this->AuthorityKeyIdentifier = array(
|
860 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
861 |
-
'children' => array(
|
862 |
-
'keyIdentifier' => array(
|
863 |
-
'constant' => 0,
|
864 |
-
'optional' => true,
|
865 |
-
'implicit' => true
|
866 |
-
) + $this->KeyIdentifier,
|
867 |
-
'authorityCertIssuer' => array(
|
868 |
-
'constant' => 1,
|
869 |
-
'optional' => true,
|
870 |
-
'implicit' => true
|
871 |
-
) + $GeneralNames,
|
872 |
-
'authorityCertSerialNumber' => array(
|
873 |
-
'constant' => 2,
|
874 |
-
'optional' => true,
|
875 |
-
'implicit' => true
|
876 |
-
) + $CertificateSerialNumber
|
877 |
-
)
|
878 |
-
);
|
879 |
-
|
880 |
-
$PolicyQualifierId = array('type' => ASN1::TYPE_OBJECT_IDENTIFIER);
|
881 |
-
|
882 |
-
$PolicyQualifierInfo = array(
|
883 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
884 |
-
'children' => array(
|
885 |
-
'policyQualifierId' => $PolicyQualifierId,
|
886 |
-
'qualifier' => array('type' => ASN1::TYPE_ANY)
|
887 |
-
)
|
888 |
-
);
|
889 |
-
|
890 |
-
$CertPolicyId = array('type' => ASN1::TYPE_OBJECT_IDENTIFIER);
|
891 |
-
|
892 |
-
$PolicyInformation = array(
|
893 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
894 |
-
'children' => array(
|
895 |
-
'policyIdentifier' => $CertPolicyId,
|
896 |
-
'policyQualifiers' => array(
|
897 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
898 |
-
'min' => 0,
|
899 |
-
'max' => -1,
|
900 |
-
'optional' => true,
|
901 |
-
'children' => $PolicyQualifierInfo
|
902 |
-
)
|
903 |
-
)
|
904 |
-
);
|
905 |
-
|
906 |
-
$this->CertificatePolicies = array(
|
907 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
908 |
-
'min' => 1,
|
909 |
-
'max' => -1,
|
910 |
-
'children' => $PolicyInformation
|
911 |
-
);
|
912 |
-
|
913 |
-
$this->PolicyMappings = array(
|
914 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
915 |
-
'min' => 1,
|
916 |
-
'max' => -1,
|
917 |
-
'children' => array(
|
918 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
919 |
-
'children' => array(
|
920 |
-
'issuerDomainPolicy' => $CertPolicyId,
|
921 |
-
'subjectDomainPolicy' => $CertPolicyId
|
922 |
-
)
|
923 |
-
)
|
924 |
-
);
|
925 |
-
|
926 |
-
$KeyPurposeId = array('type' => ASN1::TYPE_OBJECT_IDENTIFIER);
|
927 |
-
|
928 |
-
$this->ExtKeyUsageSyntax = array(
|
929 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
930 |
-
'min' => 1,
|
931 |
-
'max' => -1,
|
932 |
-
'children' => $KeyPurposeId
|
933 |
-
);
|
934 |
-
|
935 |
-
$AccessDescription = array(
|
936 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
937 |
-
'children' => array(
|
938 |
-
'accessMethod' => array('type' => ASN1::TYPE_OBJECT_IDENTIFIER),
|
939 |
-
'accessLocation' => $GeneralName
|
940 |
-
)
|
941 |
-
);
|
942 |
-
|
943 |
-
$this->AuthorityInfoAccessSyntax = array(
|
944 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
945 |
-
'min' => 1,
|
946 |
-
'max' => -1,
|
947 |
-
'children' => $AccessDescription
|
948 |
-
);
|
949 |
-
|
950 |
-
$this->SubjectAltName = $GeneralNames;
|
951 |
-
|
952 |
-
$this->PrivateKeyUsagePeriod = array(
|
953 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
954 |
-
'children' => array(
|
955 |
-
'notBefore' => array(
|
956 |
-
'constant' => 0,
|
957 |
-
'optional' => true,
|
958 |
-
'implicit' => true,
|
959 |
-
'type' => ASN1::TYPE_GENERALIZED_TIME),
|
960 |
-
'notAfter' => array(
|
961 |
-
'constant' => 1,
|
962 |
-
'optional' => true,
|
963 |
-
'implicit' => true,
|
964 |
-
'type' => ASN1::TYPE_GENERALIZED_TIME)
|
965 |
-
)
|
966 |
-
);
|
967 |
-
|
968 |
-
$BaseDistance = array('type' => ASN1::TYPE_INTEGER);
|
969 |
-
|
970 |
-
$GeneralSubtree = array(
|
971 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
972 |
-
'children' => array(
|
973 |
-
'base' => $GeneralName,
|
974 |
-
'minimum' => array(
|
975 |
-
'constant' => 0,
|
976 |
-
'optional' => true,
|
977 |
-
'implicit' => true,
|
978 |
-
'default' => new BigInteger(0)
|
979 |
-
) + $BaseDistance,
|
980 |
-
'maximum' => array(
|
981 |
-
'constant' => 1,
|
982 |
-
'optional' => true,
|
983 |
-
'implicit' => true,
|
984 |
-
) + $BaseDistance
|
985 |
-
)
|
986 |
-
);
|
987 |
-
|
988 |
-
$GeneralSubtrees = array(
|
989 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
990 |
-
'min' => 1,
|
991 |
-
'max' => -1,
|
992 |
-
'children' => $GeneralSubtree
|
993 |
-
);
|
994 |
-
|
995 |
-
$this->NameConstraints = array(
|
996 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
997 |
-
'children' => array(
|
998 |
-
'permittedSubtrees' => array(
|
999 |
-
'constant' => 0,
|
1000 |
-
'optional' => true,
|
1001 |
-
'implicit' => true
|
1002 |
-
) + $GeneralSubtrees,
|
1003 |
-
'excludedSubtrees' => array(
|
1004 |
-
'constant' => 1,
|
1005 |
-
'optional' => true,
|
1006 |
-
'implicit' => true
|
1007 |
-
) + $GeneralSubtrees
|
1008 |
-
)
|
1009 |
-
);
|
1010 |
-
|
1011 |
-
$this->CPSuri = array('type' => ASN1::TYPE_IA5_STRING);
|
1012 |
-
|
1013 |
-
$DisplayText = array(
|
1014 |
-
'type' => ASN1::TYPE_CHOICE,
|
1015 |
-
'children' => array(
|
1016 |
-
'ia5String' => array('type' => ASN1::TYPE_IA5_STRING),
|
1017 |
-
'visibleString' => array('type' => ASN1::TYPE_VISIBLE_STRING),
|
1018 |
-
'bmpString' => array('type' => ASN1::TYPE_BMP_STRING),
|
1019 |
-
'utf8String' => array('type' => ASN1::TYPE_UTF8_STRING)
|
1020 |
-
)
|
1021 |
-
);
|
1022 |
-
|
1023 |
-
$NoticeReference = array(
|
1024 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
1025 |
-
'children' => array(
|
1026 |
-
'organization' => $DisplayText,
|
1027 |
-
'noticeNumbers' => array(
|
1028 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
1029 |
-
'min' => 1,
|
1030 |
-
'max' => 200,
|
1031 |
-
'children' => array('type' => ASN1::TYPE_INTEGER)
|
1032 |
-
)
|
1033 |
-
)
|
1034 |
-
);
|
1035 |
-
|
1036 |
-
$this->UserNotice = array(
|
1037 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
1038 |
-
'children' => array(
|
1039 |
-
'noticeRef' => array(
|
1040 |
-
'optional' => true,
|
1041 |
-
'implicit' => true
|
1042 |
-
) + $NoticeReference,
|
1043 |
-
'explicitText' => array(
|
1044 |
-
'optional' => true,
|
1045 |
-
'implicit' => true
|
1046 |
-
) + $DisplayText
|
1047 |
-
)
|
1048 |
-
);
|
1049 |
-
|
1050 |
-
// mapping is from <http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html>
|
1051 |
-
$this->netscape_cert_type = array(
|
1052 |
-
'type' => ASN1::TYPE_BIT_STRING,
|
1053 |
-
'mapping' => array(
|
1054 |
-
'SSLClient',
|
1055 |
-
'SSLServer',
|
1056 |
-
'Email',
|
1057 |
-
'ObjectSigning',
|
1058 |
-
'Reserved',
|
1059 |
-
'SSLCA',
|
1060 |
-
'EmailCA',
|
1061 |
-
'ObjectSigningCA'
|
1062 |
-
)
|
1063 |
-
);
|
1064 |
-
|
1065 |
-
$this->netscape_comment = array('type' => ASN1::TYPE_IA5_STRING);
|
1066 |
-
$this->netscape_ca_policy_url = array('type' => ASN1::TYPE_IA5_STRING);
|
1067 |
-
|
1068 |
-
// attribute is used in RFC2986 but we're using the RFC5280 definition
|
1069 |
-
|
1070 |
-
$Attribute = array(
|
1071 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
1072 |
-
'children' => array(
|
1073 |
-
'type' => $AttributeType,
|
1074 |
-
'value'=> array(
|
1075 |
-
'type' => ASN1::TYPE_SET,
|
1076 |
-
'min' => 1,
|
1077 |
-
'max' => -1,
|
1078 |
-
'children' => $this->AttributeValue
|
1079 |
-
)
|
1080 |
-
)
|
1081 |
-
);
|
1082 |
-
|
1083 |
-
$this->SubjectDirectoryAttributes = array(
|
1084 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
1085 |
-
'min' => 1,
|
1086 |
-
'max' => -1,
|
1087 |
-
'children' => $Attribute
|
1088 |
-
);
|
1089 |
-
|
1090 |
-
// adapted from <http://tools.ietf.org/html/rfc2986>
|
1091 |
-
|
1092 |
-
$Attributes = array(
|
1093 |
-
'type' => ASN1::TYPE_SET,
|
1094 |
-
'min' => 1,
|
1095 |
-
'max' => -1,
|
1096 |
-
'children' => $Attribute
|
1097 |
-
);
|
1098 |
-
|
1099 |
-
$CertificationRequestInfo = array(
|
1100 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
1101 |
-
'children' => array(
|
1102 |
-
'version' => array(
|
1103 |
-
'type' => ASN1::TYPE_INTEGER,
|
1104 |
-
'mapping' => array('v1')
|
1105 |
-
),
|
1106 |
-
'subject' => $this->Name,
|
1107 |
-
'subjectPKInfo' => $SubjectPublicKeyInfo,
|
1108 |
-
'attributes' => array(
|
1109 |
-
'constant' => 0,
|
1110 |
-
'optional' => true,
|
1111 |
-
'implicit' => true
|
1112 |
-
) + $Attributes,
|
1113 |
-
)
|
1114 |
-
);
|
1115 |
-
|
1116 |
-
$this->CertificationRequest = array(
|
1117 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
1118 |
-
'children' => array(
|
1119 |
-
'certificationRequestInfo' => $CertificationRequestInfo,
|
1120 |
-
'signatureAlgorithm' => $AlgorithmIdentifier,
|
1121 |
-
'signature' => array('type' => ASN1::TYPE_BIT_STRING)
|
1122 |
-
)
|
1123 |
-
);
|
1124 |
-
|
1125 |
-
$RevokedCertificate = array(
|
1126 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
1127 |
-
'children' => array(
|
1128 |
-
'userCertificate' => $CertificateSerialNumber,
|
1129 |
-
'revocationDate' => $Time,
|
1130 |
-
'crlEntryExtensions' => array(
|
1131 |
-
'optional' => true
|
1132 |
-
) + $this->Extensions
|
1133 |
-
)
|
1134 |
-
);
|
1135 |
-
|
1136 |
-
$TBSCertList = array(
|
1137 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
1138 |
-
'children' => array(
|
1139 |
-
'version' => array(
|
1140 |
-
'optional' => true,
|
1141 |
-
'default' => 'v1'
|
1142 |
-
) + $Version,
|
1143 |
-
'signature' => $AlgorithmIdentifier,
|
1144 |
-
'issuer' => $this->Name,
|
1145 |
-
'thisUpdate' => $Time,
|
1146 |
-
'nextUpdate' => array(
|
1147 |
-
'optional' => true
|
1148 |
-
) + $Time,
|
1149 |
-
'revokedCertificates' => array(
|
1150 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
1151 |
-
'optional' => true,
|
1152 |
-
'min' => 0,
|
1153 |
-
'max' => -1,
|
1154 |
-
'children' => $RevokedCertificate
|
1155 |
-
),
|
1156 |
-
'crlExtensions' => array(
|
1157 |
-
'constant' => 0,
|
1158 |
-
'optional' => true,
|
1159 |
-
'explicit' => true
|
1160 |
-
) + $this->Extensions
|
1161 |
-
)
|
1162 |
-
);
|
1163 |
-
|
1164 |
-
$this->CertificateList = array(
|
1165 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
1166 |
-
'children' => array(
|
1167 |
-
'tbsCertList' => $TBSCertList,
|
1168 |
-
'signatureAlgorithm' => $AlgorithmIdentifier,
|
1169 |
-
'signature' => array('type' => ASN1::TYPE_BIT_STRING)
|
1170 |
-
)
|
1171 |
-
);
|
1172 |
-
|
1173 |
-
$this->CRLNumber = array('type' => ASN1::TYPE_INTEGER);
|
1174 |
-
|
1175 |
-
$this->CRLReason = array('type' => ASN1::TYPE_ENUMERATED,
|
1176 |
-
'mapping' => array(
|
1177 |
-
'unspecified',
|
1178 |
-
'keyCompromise',
|
1179 |
-
'cACompromise',
|
1180 |
-
'affiliationChanged',
|
1181 |
-
'superseded',
|
1182 |
-
'cessationOfOperation',
|
1183 |
-
'certificateHold',
|
1184 |
-
// Value 7 is not used.
|
1185 |
-
8 => 'removeFromCRL',
|
1186 |
-
'privilegeWithdrawn',
|
1187 |
-
'aACompromise'
|
1188 |
-
)
|
1189 |
-
);
|
1190 |
-
|
1191 |
-
$this->IssuingDistributionPoint = array('type' => ASN1::TYPE_SEQUENCE,
|
1192 |
-
'children' => array(
|
1193 |
-
'distributionPoint' => array(
|
1194 |
-
'constant' => 0,
|
1195 |
-
'optional' => true,
|
1196 |
-
'explicit' => true
|
1197 |
-
) + $DistributionPointName,
|
1198 |
-
'onlyContainsUserCerts' => array(
|
1199 |
-
'type' => ASN1::TYPE_BOOLEAN,
|
1200 |
-
'constant' => 1,
|
1201 |
-
'optional' => true,
|
1202 |
-
'default' => false,
|
1203 |
-
'implicit' => true
|
1204 |
-
),
|
1205 |
-
'onlyContainsCACerts' => array(
|
1206 |
-
'type' => ASN1::TYPE_BOOLEAN,
|
1207 |
-
'constant' => 2,
|
1208 |
-
'optional' => true,
|
1209 |
-
'default' => false,
|
1210 |
-
'implicit' => true
|
1211 |
-
),
|
1212 |
-
'onlySomeReasons' => array(
|
1213 |
-
'constant' => 3,
|
1214 |
-
'optional' => true,
|
1215 |
-
'implicit' => true
|
1216 |
-
) + $ReasonFlags,
|
1217 |
-
'indirectCRL' => array(
|
1218 |
-
'type' => ASN1::TYPE_BOOLEAN,
|
1219 |
-
'constant' => 4,
|
1220 |
-
'optional' => true,
|
1221 |
-
'default' => false,
|
1222 |
-
'implicit' => true
|
1223 |
-
),
|
1224 |
-
'onlyContainsAttributeCerts' => array(
|
1225 |
-
'type' => ASN1::TYPE_BOOLEAN,
|
1226 |
-
'constant' => 5,
|
1227 |
-
'optional' => true,
|
1228 |
-
'default' => false,
|
1229 |
-
'implicit' => true
|
1230 |
-
)
|
1231 |
-
)
|
1232 |
-
);
|
1233 |
-
|
1234 |
-
$this->InvalidityDate = array('type' => ASN1::TYPE_GENERALIZED_TIME);
|
1235 |
-
|
1236 |
-
$this->CertificateIssuer = $GeneralNames;
|
1237 |
-
|
1238 |
-
$this->HoldInstructionCode = array('type' => ASN1::TYPE_OBJECT_IDENTIFIER);
|
1239 |
-
|
1240 |
-
$PublicKeyAndChallenge = array(
|
1241 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
1242 |
-
'children' => array(
|
1243 |
-
'spki' => $SubjectPublicKeyInfo,
|
1244 |
-
'challenge' => array('type' => ASN1::TYPE_IA5_STRING)
|
1245 |
-
)
|
1246 |
-
);
|
1247 |
-
|
1248 |
-
$this->SignedPublicKeyAndChallenge = array(
|
1249 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
1250 |
-
'children' => array(
|
1251 |
-
'publicKeyAndChallenge' => $PublicKeyAndChallenge,
|
1252 |
-
'signatureAlgorithm' => $AlgorithmIdentifier,
|
1253 |
-
'signature' => array('type' => ASN1::TYPE_BIT_STRING)
|
1254 |
-
)
|
1255 |
-
);
|
1256 |
-
|
1257 |
-
$this->PostalAddress = array(
|
1258 |
-
'type' => ASN1::TYPE_SEQUENCE,
|
1259 |
-
'optional' => true,
|
1260 |
-
'min' => 1,
|
1261 |
-
'max' => -1,
|
1262 |
-
'children' => $this->DirectoryString
|
1263 |
-
);
|
1264 |
-
|
1265 |
-
// OIDs from RFC5280 and those RFCs mentioned in RFC5280#section-4.1.1.2
|
1266 |
-
$this->oids = array(
|
1267 |
-
'1.3.6.1.5.5.7' => 'id-pkix',
|
1268 |
-
'1.3.6.1.5.5.7.1' => 'id-pe',
|
1269 |
-
'1.3.6.1.5.5.7.2' => 'id-qt',
|
1270 |
-
'1.3.6.1.5.5.7.3' => 'id-kp',
|
1271 |
-
'1.3.6.1.5.5.7.48' => 'id-ad',
|
1272 |
-
'1.3.6.1.5.5.7.2.1' => 'id-qt-cps',
|
1273 |
-
'1.3.6.1.5.5.7.2.2' => 'id-qt-unotice',
|
1274 |
-
'1.3.6.1.5.5.7.48.1' =>'id-ad-ocsp',
|
1275 |
-
'1.3.6.1.5.5.7.48.2' => 'id-ad-caIssuers',
|
1276 |
-
'1.3.6.1.5.5.7.48.3' => 'id-ad-timeStamping',
|
1277 |
-
'1.3.6.1.5.5.7.48.5' => 'id-ad-caRepository',
|
1278 |
-
'2.5.4' => 'id-at',
|
1279 |
-
'2.5.4.41' => 'id-at-name',
|
1280 |
-
'2.5.4.4' => 'id-at-surname',
|
1281 |
-
'2.5.4.42' => 'id-at-givenName',
|
1282 |
-
'2.5.4.43' => 'id-at-initials',
|
1283 |
-
'2.5.4.44' => 'id-at-generationQualifier',
|
1284 |
-
'2.5.4.3' => 'id-at-commonName',
|
1285 |
-
'2.5.4.7' => 'id-at-localityName',
|
1286 |
-
'2.5.4.8' => 'id-at-stateOrProvinceName',
|
1287 |
-
'2.5.4.10' => 'id-at-organizationName',
|
1288 |
-
'2.5.4.11' => 'id-at-organizationalUnitName',
|
1289 |
-
'2.5.4.12' => 'id-at-title',
|
1290 |
-
'2.5.4.13' => 'id-at-description',
|
1291 |
-
'2.5.4.46' => 'id-at-dnQualifier',
|
1292 |
-
'2.5.4.6' => 'id-at-countryName',
|
1293 |
-
'2.5.4.5' => 'id-at-serialNumber',
|
1294 |
-
'2.5.4.65' => 'id-at-pseudonym',
|
1295 |
-
'2.5.4.17' => 'id-at-postalCode',
|
1296 |
-
'2.5.4.9' => 'id-at-streetAddress',
|
1297 |
-
'2.5.4.45' => 'id-at-uniqueIdentifier',
|
1298 |
-
'2.5.4.72' => 'id-at-role',
|
1299 |
-
'2.5.4.16' => 'id-at-postalAddress',
|
1300 |
-
|
1301 |
-
'0.9.2342.19200300.100.1.25' => 'id-domainComponent',
|
1302 |
-
'1.2.840.113549.1.9' => 'pkcs-9',
|
1303 |
-
'1.2.840.113549.1.9.1' => 'pkcs-9-at-emailAddress',
|
1304 |
-
'2.5.29' => 'id-ce',
|
1305 |
-
'2.5.29.35' => 'id-ce-authorityKeyIdentifier',
|
1306 |
-
'2.5.29.14' => 'id-ce-subjectKeyIdentifier',
|
1307 |
-
'2.5.29.15' => 'id-ce-keyUsage',
|
1308 |
-
'2.5.29.16' => 'id-ce-privateKeyUsagePeriod',
|
1309 |
-
'2.5.29.32' => 'id-ce-certificatePolicies',
|
1310 |
-
'2.5.29.32.0' => 'anyPolicy',
|
1311 |
-
|
1312 |
-
'2.5.29.33' => 'id-ce-policyMappings',
|
1313 |
-
'2.5.29.17' => 'id-ce-subjectAltName',
|
1314 |
-
'2.5.29.18' => 'id-ce-issuerAltName',
|
1315 |
-
'2.5.29.9' => 'id-ce-subjectDirectoryAttributes',
|
1316 |
-
'2.5.29.19' => 'id-ce-basicConstraints',
|
1317 |
-
'2.5.29.30' => 'id-ce-nameConstraints',
|
1318 |
-
'2.5.29.36' => 'id-ce-policyConstraints',
|
1319 |
-
'2.5.29.31' => 'id-ce-cRLDistributionPoints',
|
1320 |
-
'2.5.29.37' => 'id-ce-extKeyUsage',
|
1321 |
-
'2.5.29.37.0' => 'anyExtendedKeyUsage',
|
1322 |
-
'1.3.6.1.5.5.7.3.1' => 'id-kp-serverAuth',
|
1323 |
-
'1.3.6.1.5.5.7.3.2' => 'id-kp-clientAuth',
|
1324 |
-
'1.3.6.1.5.5.7.3.3' => 'id-kp-codeSigning',
|
1325 |
-
'1.3.6.1.5.5.7.3.4' => 'id-kp-emailProtection',
|
1326 |
-
'1.3.6.1.5.5.7.3.8' => 'id-kp-timeStamping',
|
1327 |
-
'1.3.6.1.5.5.7.3.9' => 'id-kp-OCSPSigning',
|
1328 |
-
'2.5.29.54' => 'id-ce-inhibitAnyPolicy',
|
1329 |
-
'2.5.29.46' => 'id-ce-freshestCRL',
|
1330 |
-
'1.3.6.1.5.5.7.1.1' => 'id-pe-authorityInfoAccess',
|
1331 |
-
'1.3.6.1.5.5.7.1.11' => 'id-pe-subjectInfoAccess',
|
1332 |
-
'2.5.29.20' => 'id-ce-cRLNumber',
|
1333 |
-
'2.5.29.28' => 'id-ce-issuingDistributionPoint',
|
1334 |
-
'2.5.29.27' => 'id-ce-deltaCRLIndicator',
|
1335 |
-
'2.5.29.21' => 'id-ce-cRLReasons',
|
1336 |
-
'2.5.29.29' => 'id-ce-certificateIssuer',
|
1337 |
-
'2.5.29.23' => 'id-ce-holdInstructionCode',
|
1338 |
-
'1.2.840.10040.2' => 'holdInstruction',
|
1339 |
-
'1.2.840.10040.2.1' => 'id-holdinstruction-none',
|
1340 |
-
'1.2.840.10040.2.2' => 'id-holdinstruction-callissuer',
|
1341 |
-
'1.2.840.10040.2.3' => 'id-holdinstruction-reject',
|
1342 |
-
'2.5.29.24' => 'id-ce-invalidityDate',
|
1343 |
-
|
1344 |
-
'1.2.840.113549.2.2' => 'md2',
|
1345 |
-
'1.2.840.113549.2.5' => 'md5',
|
1346 |
-
'1.3.14.3.2.26' => 'id-sha1',
|
1347 |
-
'1.2.840.10040.4.1' => 'id-dsa',
|
1348 |
-
'1.2.840.10040.4.3' => 'id-dsa-with-sha1',
|
1349 |
-
'1.2.840.113549.1.1' => 'pkcs-1',
|
1350 |
-
'1.2.840.113549.1.1.1' => 'rsaEncryption',
|
1351 |
-
'1.2.840.113549.1.1.2' => 'md2WithRSAEncryption',
|
1352 |
-
'1.2.840.113549.1.1.4' => 'md5WithRSAEncryption',
|
1353 |
-
'1.2.840.113549.1.1.5' => 'sha1WithRSAEncryption',
|
1354 |
-
'1.2.840.10046.2.1' => 'dhpublicnumber',
|
1355 |
-
'2.16.840.1.101.2.1.1.22' => 'id-keyExchangeAlgorithm',
|
1356 |
-
'1.2.840.10045' => 'ansi-X9-62',
|
1357 |
-
'1.2.840.10045.4' => 'id-ecSigType',
|
1358 |
-
'1.2.840.10045.4.1' => 'ecdsa-with-SHA1',
|
1359 |
-
'1.2.840.10045.1' => 'id-fieldType',
|
1360 |
-
'1.2.840.10045.1.1' => 'prime-field',
|
1361 |
-
'1.2.840.10045.1.2' => 'characteristic-two-field',
|
1362 |
-
'1.2.840.10045.1.2.3' => 'id-characteristic-two-basis',
|
1363 |
-
'1.2.840.10045.1.2.3.1' => 'gnBasis',
|
1364 |
-
'1.2.840.10045.1.2.3.2' => 'tpBasis',
|
1365 |
-
'1.2.840.10045.1.2.3.3' => 'ppBasis',
|
1366 |
-
'1.2.840.10045.2' => 'id-publicKeyType',
|
1367 |
-
'1.2.840.10045.2.1' => 'id-ecPublicKey',
|
1368 |
-
'1.2.840.10045.3' => 'ellipticCurve',
|
1369 |
-
'1.2.840.10045.3.0' => 'c-TwoCurve',
|
1370 |
-
'1.2.840.10045.3.0.1' => 'c2pnb163v1',
|
1371 |
-
'1.2.840.10045.3.0.2' => 'c2pnb163v2',
|
1372 |
-
'1.2.840.10045.3.0.3' => 'c2pnb163v3',
|
1373 |
-
'1.2.840.10045.3.0.4' => 'c2pnb176w1',
|
1374 |
-
'1.2.840.10045.3.0.5' => 'c2pnb191v1',
|
1375 |
-
'1.2.840.10045.3.0.6' => 'c2pnb191v2',
|
1376 |
-
'1.2.840.10045.3.0.7' => 'c2pnb191v3',
|
1377 |
-
'1.2.840.10045.3.0.8' => 'c2pnb191v4',
|
1378 |
-
'1.2.840.10045.3.0.9' => 'c2pnb191v5',
|
1379 |
-
'1.2.840.10045.3.0.10' => 'c2pnb208w1',
|
1380 |
-
'1.2.840.10045.3.0.11' => 'c2pnb239v1',
|
1381 |
-
'1.2.840.10045.3.0.12' => 'c2pnb239v2',
|
1382 |
-
'1.2.840.10045.3.0.13' => 'c2pnb239v3',
|
1383 |
-
'1.2.840.10045.3.0.14' => 'c2pnb239v4',
|
1384 |
-
'1.2.840.10045.3.0.15' => 'c2pnb239v5',
|
1385 |
-
'1.2.840.10045.3.0.16' => 'c2pnb272w1',
|
1386 |
-
'1.2.840.10045.3.0.17' => 'c2pnb304w1',
|
1387 |
-
'1.2.840.10045.3.0.18' => 'c2pnb359v1',
|
1388 |
-
'1.2.840.10045.3.0.19' => 'c2pnb368w1',
|
1389 |
-
'1.2.840.10045.3.0.20' => 'c2pnb431r1',
|
1390 |
-
'1.2.840.10045.3.1' => 'primeCurve',
|
1391 |
-
'1.2.840.10045.3.1.1' => 'prime192v1',
|
1392 |
-
'1.2.840.10045.3.1.2' => 'prime192v2',
|
1393 |
-
'1.2.840.10045.3.1.3' => 'prime192v3',
|
1394 |
-
'1.2.840.10045.3.1.4' => 'prime239v1',
|
1395 |
-
'1.2.840.10045.3.1.5' => 'prime239v2',
|
1396 |
-
'1.2.840.10045.3.1.6' => 'prime239v3',
|
1397 |
-
'1.2.840.10045.3.1.7' => 'prime256v1',
|
1398 |
-
'1.2.840.113549.1.1.7' => 'id-RSAES-OAEP',
|
1399 |
-
'1.2.840.113549.1.1.9' => 'id-pSpecified',
|
1400 |
-
'1.2.840.113549.1.1.10' => 'id-RSASSA-PSS',
|
1401 |
-
'1.2.840.113549.1.1.8' => 'id-mgf1',
|
1402 |
-
'1.2.840.113549.1.1.14' => 'sha224WithRSAEncryption',
|
1403 |
-
'1.2.840.113549.1.1.11' => 'sha256WithRSAEncryption',
|
1404 |
-
'1.2.840.113549.1.1.12' => 'sha384WithRSAEncryption',
|
1405 |
-
'1.2.840.113549.1.1.13' => 'sha512WithRSAEncryption',
|
1406 |
-
'2.16.840.1.101.3.4.2.4' => 'id-sha224',
|
1407 |
-
'2.16.840.1.101.3.4.2.1' => 'id-sha256',
|
1408 |
-
'2.16.840.1.101.3.4.2.2' => 'id-sha384',
|
1409 |
-
'2.16.840.1.101.3.4.2.3' => 'id-sha512',
|
1410 |
-
'1.2.643.2.2.4' => 'id-GostR3411-94-with-GostR3410-94',
|
1411 |
-
'1.2.643.2.2.3' => 'id-GostR3411-94-with-GostR3410-2001',
|
1412 |
-
'1.2.643.2.2.20' => 'id-GostR3410-2001',
|
1413 |
-
'1.2.643.2.2.19' => 'id-GostR3410-94',
|
1414 |
-
// Netscape Object Identifiers from "Netscape Certificate Extensions"
|
1415 |
-
'2.16.840.1.113730' => 'netscape',
|
1416 |
-
'2.16.840.1.113730.1' => 'netscape-cert-extension',
|
1417 |
-
'2.16.840.1.113730.1.1' => 'netscape-cert-type',
|
1418 |
-
'2.16.840.1.113730.1.13' => 'netscape-comment',
|
1419 |
-
'2.16.840.1.113730.1.8' => 'netscape-ca-policy-url',
|
1420 |
-
// the following are X.509 extensions not supported by phpseclib
|
1421 |
-
'1.3.6.1.5.5.7.1.12' => 'id-pe-logotype',
|
1422 |
-
'1.2.840.113533.7.65.0' => 'entrustVersInfo',
|
1423 |
-
'2.16.840.1.113733.1.6.9' => 'verisignPrivate',
|
1424 |
-
// for Certificate Signing Requests
|
1425 |
-
// see http://tools.ietf.org/html/rfc2985
|
1426 |
-
'1.2.840.113549.1.9.2' => 'pkcs-9-at-unstructuredName', // PKCS #9 unstructured name
|
1427 |
-
'1.2.840.113549.1.9.7' => 'pkcs-9-at-challengePassword', // Challenge password for certificate revocations
|
1428 |
-
'1.2.840.113549.1.9.14' => 'pkcs-9-at-extensionRequest' // Certificate extension request
|
1429 |
-
);
|
1430 |
-
}
|
1431 |
-
|
1432 |
-
/**
|
1433 |
-
* Load X.509 certificate
|
1434 |
-
*
|
1435 |
-
* Returns an associative array describing the X.509 cert or a false if the cert failed to load
|
1436 |
-
*
|
1437 |
-
* @param string $cert
|
1438 |
-
* @param int $mode
|
1439 |
-
* @access public
|
1440 |
-
* @return mixed
|
1441 |
-
*/
|
1442 |
-
function loadX509($cert, $mode = self::FORMAT_AUTO_DETECT)
|
1443 |
-
{
|
1444 |
-
if (is_array($cert) && isset($cert['tbsCertificate'])) {
|
1445 |
-
unset($this->currentCert);
|
1446 |
-
unset($this->currentKeyIdentifier);
|
1447 |
-
$this->dn = $cert['tbsCertificate']['subject'];
|
1448 |
-
if (!isset($this->dn)) {
|
1449 |
-
return false;
|
1450 |
-
}
|
1451 |
-
$this->currentCert = $cert;
|
1452 |
-
|
1453 |
-
$currentKeyIdentifier = $this->getExtension('id-ce-subjectKeyIdentifier');
|
1454 |
-
$this->currentKeyIdentifier = is_string($currentKeyIdentifier) ? $currentKeyIdentifier : null;
|
1455 |
-
|
1456 |
-
unset($this->signatureSubject);
|
1457 |
-
|
1458 |
-
return $cert;
|
1459 |
-
}
|
1460 |
-
|
1461 |
-
$asn1 = new ASN1();
|
1462 |
-
|
1463 |
-
if ($mode != self::FORMAT_DER) {
|
1464 |
-
$newcert = $this->_extractBER($cert);
|
1465 |
-
if ($mode == self::FORMAT_PEM && $cert == $newcert) {
|
1466 |
-
return false;
|
1467 |
-
}
|
1468 |
-
$cert = $newcert;
|
1469 |
-
}
|
1470 |
-
|
1471 |
-
if ($cert === false) {
|
1472 |
-
$this->currentCert = false;
|
1473 |
-
return false;
|
1474 |
-
}
|
1475 |
-
|
1476 |
-
$asn1->loadOIDs($this->oids);
|
1477 |
-
$decoded = $asn1->decodeBER($cert);
|
1478 |
-
|
1479 |
-
if (!empty($decoded)) {
|
1480 |
-
$x509 = $asn1->asn1map($decoded[0], $this->Certificate);
|
1481 |
-
}
|
1482 |
-
if (!isset($x509) || $x509 === false) {
|
1483 |
-
$this->currentCert = false;
|
1484 |
-
return false;
|
1485 |
-
}
|
1486 |
-
|
1487 |
-
$this->signatureSubject = substr($cert, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
|
1488 |
-
|
1489 |
-
if ($this->_isSubArrayValid($x509, 'tbsCertificate/extensions')) {
|
1490 |
-
$this->_mapInExtensions($x509, 'tbsCertificate/extensions', $asn1);
|
1491 |
-
}
|
1492 |
-
$this->_mapInDNs($x509, 'tbsCertificate/issuer/rdnSequence', $asn1);
|
1493 |
-
$this->_mapInDNs($x509, 'tbsCertificate/subject/rdnSequence', $asn1);
|
1494 |
-
|
1495 |
-
$key = &$x509['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'];
|
1496 |
-
$key = $this->_reformatKey($x509['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'], $key);
|
1497 |
-
|
1498 |
-
$this->currentCert = $x509;
|
1499 |
-
$this->dn = $x509['tbsCertificate']['subject'];
|
1500 |
-
|
1501 |
-
$currentKeyIdentifier = $this->getExtension('id-ce-subjectKeyIdentifier');
|
1502 |
-
$this->currentKeyIdentifier = is_string($currentKeyIdentifier) ? $currentKeyIdentifier : null;
|
1503 |
-
|
1504 |
-
return $x509;
|
1505 |
-
}
|
1506 |
-
|
1507 |
-
/**
|
1508 |
-
* Save X.509 certificate
|
1509 |
-
*
|
1510 |
-
* @param array $cert
|
1511 |
-
* @param int $format optional
|
1512 |
-
* @access public
|
1513 |
-
* @return string
|
1514 |
-
*/
|
1515 |
-
function saveX509($cert, $format = self::FORMAT_PEM)
|
1516 |
-
{
|
1517 |
-
if (!is_array($cert) || !isset($cert['tbsCertificate'])) {
|
1518 |
-
return false;
|
1519 |
-
}
|
1520 |
-
|
1521 |
-
switch (true) {
|
1522 |
-
// "case !$a: case !$b: break; default: whatever();" is the same thing as "if ($a && $b) whatever()"
|
1523 |
-
case !($algorithm = $this->_subArray($cert, 'tbsCertificate/subjectPublicKeyInfo/algorithm/algorithm')):
|
1524 |
-
case is_object($cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']):
|
1525 |
-
break;
|
1526 |
-
default:
|
1527 |
-
switch ($algorithm) {
|
1528 |
-
case 'rsaEncryption':
|
1529 |
-
$cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']
|
1530 |
-
= base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'])));
|
1531 |
-
/* "[For RSA keys] the parameters field MUST have ASN.1 type NULL for this algorithm identifier."
|
1532 |
-
-- https://tools.ietf.org/html/rfc3279#section-2.3.1
|
1533 |
-
|
1534 |
-
given that and the fact that RSA keys appear ot be the only key type for which the parameters field can be blank,
|
1535 |
-
it seems like perhaps the ASN.1 description ought not say the parameters field is OPTIONAL, but whatever.
|
1536 |
-
*/
|
1537 |
-
$cert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['parameters'] = null;
|
1538 |
-
// https://tools.ietf.org/html/rfc3279#section-2.2.1
|
1539 |
-
$cert['signatureAlgorithm']['parameters'] = null;
|
1540 |
-
$cert['tbsCertificate']['signature']['parameters'] = null;
|
1541 |
-
}
|
1542 |
-
}
|
1543 |
-
|
1544 |
-
$asn1 = new ASN1();
|
1545 |
-
$asn1->loadOIDs($this->oids);
|
1546 |
-
|
1547 |
-
$filters = array();
|
1548 |
-
$type_utf8_string = array('type' => ASN1::TYPE_UTF8_STRING);
|
1549 |
-
$filters['tbsCertificate']['signature']['parameters'] = $type_utf8_string;
|
1550 |
-
$filters['tbsCertificate']['signature']['issuer']['rdnSequence']['value'] = $type_utf8_string;
|
1551 |
-
$filters['tbsCertificate']['issuer']['rdnSequence']['value'] = $type_utf8_string;
|
1552 |
-
$filters['tbsCertificate']['subject']['rdnSequence']['value'] = $type_utf8_string;
|
1553 |
-
$filters['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['parameters'] = $type_utf8_string;
|
1554 |
-
$filters['signatureAlgorithm']['parameters'] = $type_utf8_string;
|
1555 |
-
$filters['authorityCertIssuer']['directoryName']['rdnSequence']['value'] = $type_utf8_string;
|
1556 |
-
//$filters['policyQualifiers']['qualifier'] = $type_utf8_string;
|
1557 |
-
$filters['distributionPoint']['fullName']['directoryName']['rdnSequence']['value'] = $type_utf8_string;
|
1558 |
-
$filters['directoryName']['rdnSequence']['value'] = $type_utf8_string;
|
1559 |
-
|
1560 |
-
/* in the case of policyQualifiers/qualifier, the type has to be \phpseclib\File\ASN1::TYPE_IA5_STRING.
|
1561 |
-
\phpseclib\File\ASN1::TYPE_PRINTABLE_STRING will cause OpenSSL's X.509 parser to spit out random
|
1562 |
-
characters.
|
1563 |
-
*/
|
1564 |
-
$filters['policyQualifiers']['qualifier']
|
1565 |
-
= array('type' => ASN1::TYPE_IA5_STRING);
|
1566 |
-
|
1567 |
-
$asn1->loadFilters($filters);
|
1568 |
-
|
1569 |
-
$this->_mapOutExtensions($cert, 'tbsCertificate/extensions', $asn1);
|
1570 |
-
$this->_mapOutDNs($cert, 'tbsCertificate/issuer/rdnSequence', $asn1);
|
1571 |
-
$this->_mapOutDNs($cert, 'tbsCertificate/subject/rdnSequence', $asn1);
|
1572 |
-
|
1573 |
-
$cert = $asn1->encodeDER($cert, $this->Certificate);
|
1574 |
-
|
1575 |
-
switch ($format) {
|
1576 |
-
case self::FORMAT_DER:
|
1577 |
-
return $cert;
|
1578 |
-
// case self::FORMAT_PEM:
|
1579 |
-
default:
|
1580 |
-
return "-----BEGIN CERTIFICATE-----\r\n" . chunk_split(base64_encode($cert), 64) . '-----END CERTIFICATE-----';
|
1581 |
-
}
|
1582 |
-
}
|
1583 |
-
|
1584 |
-
/**
|
1585 |
-
* Map extension values from octet string to extension-specific internal
|
1586 |
-
* format.
|
1587 |
-
*
|
1588 |
-
* @param array ref $root
|
1589 |
-
* @param string $path
|
1590 |
-
* @param object $asn1
|
1591 |
-
* @access private
|
1592 |
-
*/
|
1593 |
-
function _mapInExtensions(&$root, $path, $asn1)
|
1594 |
-
{
|
1595 |
-
$extensions = &$this->_subArrayUnchecked($root, $path);
|
1596 |
-
|
1597 |
-
if ($extensions) {
|
1598 |
-
for ($i = 0; $i < count($extensions); $i++) {
|
1599 |
-
$id = $extensions[$i]['extnId'];
|
1600 |
-
$value = &$extensions[$i]['extnValue'];
|
1601 |
-
$value = base64_decode($value);
|
1602 |
-
$decoded = $asn1->decodeBER($value);
|
1603 |
-
/* [extnValue] contains the DER encoding of an ASN.1 value
|
1604 |
-
corresponding to the extension type identified by extnID */
|
1605 |
-
$map = $this->_getMapping($id);
|
1606 |
-
if (!is_bool($map)) {
|
1607 |
-
$mapped = $asn1->asn1map($decoded[0], $map, array('iPAddress' => array($this, '_decodeIP')));
|
1608 |
-
$value = $mapped === false ? $decoded[0] : $mapped;
|
1609 |
-
|
1610 |
-
if ($id == 'id-ce-certificatePolicies') {
|
1611 |
-
for ($j = 0; $j < count($value); $j++) {
|
1612 |
-
if (!isset($value[$j]['policyQualifiers'])) {
|
1613 |
-
continue;
|
1614 |
-
}
|
1615 |
-
for ($k = 0; $k < count($value[$j]['policyQualifiers']); $k++) {
|
1616 |
-
$subid = $value[$j]['policyQualifiers'][$k]['policyQualifierId'];
|
1617 |
-
$map = $this->_getMapping($subid);
|
1618 |
-
$subvalue = &$value[$j]['policyQualifiers'][$k]['qualifier'];
|
1619 |
-
if ($map !== false) {
|
1620 |
-
$decoded = $asn1->decodeBER($subvalue);
|
1621 |
-
$mapped = $asn1->asn1map($decoded[0], $map);
|
1622 |
-
$subvalue = $mapped === false ? $decoded[0] : $mapped;
|
1623 |
-
}
|
1624 |
-
}
|
1625 |
-
}
|
1626 |
-
}
|
1627 |
-
} else {
|
1628 |
-
$value = base64_encode($value);
|
1629 |
-
}
|
1630 |
-
}
|
1631 |
-
}
|
1632 |
-
}
|
1633 |
-
|
1634 |
-
/**
|
1635 |
-
* Map extension values from extension-specific internal format to
|
1636 |
-
* octet string.
|
1637 |
-
*
|
1638 |
-
* @param array ref $root
|
1639 |
-
* @param string $path
|
1640 |
-
* @param object $asn1
|
1641 |
-
* @access private
|
1642 |
-
*/
|
1643 |
-
function _mapOutExtensions(&$root, $path, $asn1)
|
1644 |
-
{
|
1645 |
-
$extensions = &$this->_subArray($root, $path);
|
1646 |
-
|
1647 |
-
if (is_array($extensions)) {
|
1648 |
-
$size = count($extensions);
|
1649 |
-
for ($i = 0; $i < $size; $i++) {
|
1650 |
-
if ($extensions[$i] instanceof Element) {
|
1651 |
-
continue;
|
1652 |
-
}
|
1653 |
-
|
1654 |
-
$id = $extensions[$i]['extnId'];
|
1655 |
-
$value = &$extensions[$i]['extnValue'];
|
1656 |
-
|
1657 |
-
switch ($id) {
|
1658 |
-
case 'id-ce-certificatePolicies':
|
1659 |
-
for ($j = 0; $j < count($value); $j++) {
|
1660 |
-
if (!isset($value[$j]['policyQualifiers'])) {
|
1661 |
-
continue;
|
1662 |
-
}
|
1663 |
-
for ($k = 0; $k < count($value[$j]['policyQualifiers']); $k++) {
|
1664 |
-
$subid = $value[$j]['policyQualifiers'][$k]['policyQualifierId'];
|
1665 |
-
$map = $this->_getMapping($subid);
|
1666 |
-
$subvalue = &$value[$j]['policyQualifiers'][$k]['qualifier'];
|
1667 |
-
if ($map !== false) {
|
1668 |
-
// by default \phpseclib\File\ASN1 will try to render qualifier as a \phpseclib\File\ASN1::TYPE_IA5_STRING since it's
|
1669 |
-
// actual type is \phpseclib\File\ASN1::TYPE_ANY
|
1670 |
-
$subvalue = new Element($asn1->encodeDER($subvalue, $map));
|
1671 |
-
}
|
1672 |
-
}
|
1673 |
-
}
|
1674 |
-
break;
|
1675 |
-
case 'id-ce-authorityKeyIdentifier': // use 00 as the serial number instead of an empty string
|
1676 |
-
if (isset($value['authorityCertSerialNumber'])) {
|
1677 |
-
if ($value['authorityCertSerialNumber']->toBytes() == '') {
|
1678 |
-
$temp = chr((ASN1::CLASS_CONTEXT_SPECIFIC << 6) | 2) . "\1\0";
|
1679 |
-
$value['authorityCertSerialNumber'] = new Element($temp);
|
1680 |
-
}
|
1681 |
-
}
|
1682 |
-
}
|
1683 |
-
|
1684 |
-
/* [extnValue] contains the DER encoding of an ASN.1 value
|
1685 |
-
corresponding to the extension type identified by extnID */
|
1686 |
-
$map = $this->_getMapping($id);
|
1687 |
-
if (is_bool($map)) {
|
1688 |
-
if (!$map) {
|
1689 |
-
user_error($id . ' is not a currently supported extension');
|
1690 |
-
unset($extensions[$i]);
|
1691 |
-
}
|
1692 |
-
} else {
|
1693 |
-
$temp = $asn1->encodeDER($value, $map, array('iPAddress' => array($this, '_encodeIP')));
|
1694 |
-
$value = base64_encode($temp);
|
1695 |
-
}
|
1696 |
-
}
|
1697 |
-
}
|
1698 |
-
}
|
1699 |
-
|
1700 |
-
/**
|
1701 |
-
* Map attribute values from ANY type to attribute-specific internal
|
1702 |
-
* format.
|
1703 |
-
*
|
1704 |
-
* @param array ref $root
|
1705 |
-
* @param string $path
|
1706 |
-
* @param object $asn1
|
1707 |
-
* @access private
|
1708 |
-
*/
|
1709 |
-
function _mapInAttributes(&$root, $path, $asn1)
|
1710 |
-
{
|
1711 |
-
$attributes = &$this->_subArray($root, $path);
|
1712 |
-
|
1713 |
-
if (is_array($attributes)) {
|
1714 |
-
for ($i = 0; $i < count($attributes); $i++) {
|
1715 |
-
$id = $attributes[$i]['type'];
|
1716 |
-
/* $value contains the DER encoding of an ASN.1 value
|
1717 |
-
corresponding to the attribute type identified by type */
|
1718 |
-
$map = $this->_getMapping($id);
|
1719 |
-
if (is_array($attributes[$i]['value'])) {
|
1720 |
-
$values = &$attributes[$i]['value'];
|
1721 |
-
for ($j = 0; $j < count($values); $j++) {
|
1722 |
-
$value = $asn1->encodeDER($values[$j], $this->AttributeValue);
|
1723 |
-
$decoded = $asn1->decodeBER($value);
|
1724 |
-
if (!is_bool($map)) {
|
1725 |
-
$mapped = $asn1->asn1map($decoded[0], $map);
|
1726 |
-
if ($mapped !== false) {
|
1727 |
-
$values[$j] = $mapped;
|
1728 |
-
}
|
1729 |
-
if ($id == 'pkcs-9-at-extensionRequest' && $this->_isSubArrayValid($values, $j)) {
|
1730 |
-
$this->_mapInExtensions($values, $j, $asn1);
|
1731 |
-
}
|
1732 |
-
} elseif ($map) {
|
1733 |
-
$values[$j] = base64_encode($value);
|
1734 |
-
}
|
1735 |
-
}
|
1736 |
-
}
|
1737 |
-
}
|
1738 |
-
}
|
1739 |
-
}
|
1740 |
-
|
1741 |
-
/**
|
1742 |
-
* Map attribute values from attribute-specific internal format to
|
1743 |
-
* ANY type.
|
1744 |
-
*
|
1745 |
-
* @param array ref $root
|
1746 |
-
* @param string $path
|
1747 |
-
* @param object $asn1
|
1748 |
-
* @access private
|
1749 |
-
*/
|
1750 |
-
function _mapOutAttributes(&$root, $path, $asn1)
|
1751 |
-
{
|
1752 |
-
$attributes = &$this->_subArray($root, $path);
|
1753 |
-
|
1754 |
-
if (is_array($attributes)) {
|
1755 |
-
$size = count($attributes);
|
1756 |
-
for ($i = 0; $i < $size; $i++) {
|
1757 |
-
/* [value] contains the DER encoding of an ASN.1 value
|
1758 |
-
corresponding to the attribute type identified by type */
|
1759 |
-
$id = $attributes[$i]['type'];
|
1760 |
-
$map = $this->_getMapping($id);
|
1761 |
-
if ($map === false) {
|
1762 |
-
user_error($id . ' is not a currently supported attribute', E_USER_NOTICE);
|
1763 |
-
unset($attributes[$i]);
|
1764 |
-
} elseif (is_array($attributes[$i]['value'])) {
|
1765 |
-
$values = &$attributes[$i]['value'];
|
1766 |
-
for ($j = 0; $j < count($values); $j++) {
|
1767 |
-
switch ($id) {
|
1768 |
-
case 'pkcs-9-at-extensionRequest':
|
1769 |
-
$this->_mapOutExtensions($values, $j, $asn1);
|
1770 |
-
break;
|
1771 |
-
}
|
1772 |
-
|
1773 |
-
if (!is_bool($map)) {
|
1774 |
-
$temp = $asn1->encodeDER($values[$j], $map);
|
1775 |
-
$decoded = $asn1->decodeBER($temp);
|
1776 |
-
$values[$j] = $asn1->asn1map($decoded[0], $this->AttributeValue);
|
1777 |
-
}
|
1778 |
-
}
|
1779 |
-
}
|
1780 |
-
}
|
1781 |
-
}
|
1782 |
-
}
|
1783 |
-
|
1784 |
-
/**
|
1785 |
-
* Map DN values from ANY type to DN-specific internal
|
1786 |
-
* format.
|
1787 |
-
*
|
1788 |
-
* @param array ref $root
|
1789 |
-
* @param string $path
|
1790 |
-
* @param object $asn1
|
1791 |
-
* @access private
|
1792 |
-
*/
|
1793 |
-
function _mapInDNs(&$root, $path, $asn1)
|
1794 |
-
{
|
1795 |
-
$dns = &$this->_subArray($root, $path);
|
1796 |
-
|
1797 |
-
if (is_array($dns)) {
|
1798 |
-
for ($i = 0; $i < count($dns); $i++) {
|
1799 |
-
for ($j = 0; $j < count($dns[$i]); $j++) {
|
1800 |
-
$type = $dns[$i][$j]['type'];
|
1801 |
-
$value = &$dns[$i][$j]['value'];
|
1802 |
-
if (is_object($value) && $value instanceof Element) {
|
1803 |
-
$map = $this->_getMapping($type);
|
1804 |
-
if (!is_bool($map)) {
|
1805 |
-
$decoded = $asn1->decodeBER($value);
|
1806 |
-
$value = $asn1->asn1map($decoded[0], $map);
|
1807 |
-
}
|
1808 |
-
}
|
1809 |
-
}
|
1810 |
-
}
|
1811 |
-
}
|
1812 |
-
}
|
1813 |
-
|
1814 |
-
/**
|
1815 |
-
* Map DN values from DN-specific internal format to
|
1816 |
-
* ANY type.
|
1817 |
-
*
|
1818 |
-
* @param array ref $root
|
1819 |
-
* @param string $path
|
1820 |
-
* @param object $asn1
|
1821 |
-
* @access private
|
1822 |
-
*/
|
1823 |
-
function _mapOutDNs(&$root, $path, $asn1)
|
1824 |
-
{
|
1825 |
-
$dns = &$this->_subArray($root, $path);
|
1826 |
-
|
1827 |
-
if (is_array($dns)) {
|
1828 |
-
$size = count($dns);
|
1829 |
-
for ($i = 0; $i < $size; $i++) {
|
1830 |
-
for ($j = 0; $j < count($dns[$i]); $j++) {
|
1831 |
-
$type = $dns[$i][$j]['type'];
|
1832 |
-
$value = &$dns[$i][$j]['value'];
|
1833 |
-
if (is_object($value) && $value instanceof Element) {
|
1834 |
-
continue;
|
1835 |
-
}
|
1836 |
-
|
1837 |
-
$map = $this->_getMapping($type);
|
1838 |
-
if (!is_bool($map)) {
|
1839 |
-
$value = new Element($asn1->encodeDER($value, $map));
|
1840 |
-
}
|
1841 |
-
}
|
1842 |
-
}
|
1843 |
-
}
|
1844 |
-
}
|
1845 |
-
|
1846 |
-
/**
|
1847 |
-
* Associate an extension ID to an extension mapping
|
1848 |
-
*
|
1849 |
-
* @param string $extnId
|
1850 |
-
* @access private
|
1851 |
-
* @return mixed
|
1852 |
-
*/
|
1853 |
-
function _getMapping($extnId)
|
1854 |
-
{
|
1855 |
-
if (!is_string($extnId)) { // eg. if it's a \phpseclib\File\ASN1\Element object
|
1856 |
-
return true;
|
1857 |
-
}
|
1858 |
-
|
1859 |
-
switch ($extnId) {
|
1860 |
-
case 'id-ce-keyUsage':
|
1861 |
-
return $this->KeyUsage;
|
1862 |
-
case 'id-ce-basicConstraints':
|
1863 |
-
return $this->BasicConstraints;
|
1864 |
-
case 'id-ce-subjectKeyIdentifier':
|
1865 |
-
return $this->KeyIdentifier;
|
1866 |
-
case 'id-ce-cRLDistributionPoints':
|
1867 |
-
return $this->CRLDistributionPoints;
|
1868 |
-
case 'id-ce-authorityKeyIdentifier':
|
1869 |
-
return $this->AuthorityKeyIdentifier;
|
1870 |
-
case 'id-ce-certificatePolicies':
|
1871 |
-
return $this->CertificatePolicies;
|
1872 |
-
case 'id-ce-extKeyUsage':
|
1873 |
-
return $this->ExtKeyUsageSyntax;
|
1874 |
-
case 'id-pe-authorityInfoAccess':
|
1875 |
-
return $this->AuthorityInfoAccessSyntax;
|
1876 |
-
case 'id-ce-subjectAltName':
|
1877 |
-
return $this->SubjectAltName;
|
1878 |
-
case 'id-ce-subjectDirectoryAttributes':
|
1879 |
-
return $this->SubjectDirectoryAttributes;
|
1880 |
-
case 'id-ce-privateKeyUsagePeriod':
|
1881 |
-
return $this->PrivateKeyUsagePeriod;
|
1882 |
-
case 'id-ce-issuerAltName':
|
1883 |
-
return $this->IssuerAltName;
|
1884 |
-
case 'id-ce-policyMappings':
|
1885 |
-
return $this->PolicyMappings;
|
1886 |
-
case 'id-ce-nameConstraints':
|
1887 |
-
return $this->NameConstraints;
|
1888 |
-
|
1889 |
-
case 'netscape-cert-type':
|
1890 |
-
return $this->netscape_cert_type;
|
1891 |
-
case 'netscape-comment':
|
1892 |
-
return $this->netscape_comment;
|
1893 |
-
case 'netscape-ca-policy-url':
|
1894 |
-
return $this->netscape_ca_policy_url;
|
1895 |
-
|
1896 |
-
// since id-qt-cps isn't a constructed type it will have already been decoded as a string by the time it gets
|
1897 |
-
// back around to asn1map() and we don't want it decoded again.
|
1898 |
-
//case 'id-qt-cps':
|
1899 |
-
// return $this->CPSuri;
|
1900 |
-
case 'id-qt-unotice':
|
1901 |
-
return $this->UserNotice;
|
1902 |
-
|
1903 |
-
// the following OIDs are unsupported but we don't want them to give notices when calling saveX509().
|
1904 |
-
case 'id-pe-logotype': // http://www.ietf.org/rfc/rfc3709.txt
|
1905 |
-
case 'entrustVersInfo':
|
1906 |
-
// http://support.microsoft.com/kb/287547
|
1907 |
-
case '1.3.6.1.4.1.311.20.2': // szOID_ENROLL_CERTTYPE_EXTENSION
|
1908 |
-
case '1.3.6.1.4.1.311.21.1': // szOID_CERTSRV_CA_VERSION
|
1909 |
-
// "SET Secure Electronic Transaction Specification"
|
1910 |
-
// http://www.maithean.com/docs/set_bk3.pdf
|
1911 |
-
case '2.23.42.7.0': // id-set-hashedRootKey
|
1912 |
-
// "Certificate Transparency"
|
1913 |
-
// https://tools.ietf.org/html/rfc6962
|
1914 |
-
case '1.3.6.1.4.1.11129.2.4.2':
|
1915 |
-
return true;
|
1916 |
-
|
1917 |
-
// CSR attributes
|
1918 |
-
case 'pkcs-9-at-unstructuredName':
|
1919 |
-
return $this->PKCS9String;
|
1920 |
-
case 'pkcs-9-at-challengePassword':
|
1921 |
-
return $this->DirectoryString;
|
1922 |
-
case 'pkcs-9-at-extensionRequest':
|
1923 |
-
return $this->Extensions;
|
1924 |
-
|
1925 |
-
// CRL extensions.
|
1926 |
-
case 'id-ce-cRLNumber':
|
1927 |
-
return $this->CRLNumber;
|
1928 |
-
case 'id-ce-deltaCRLIndicator':
|
1929 |
-
return $this->CRLNumber;
|
1930 |
-
case 'id-ce-issuingDistributionPoint':
|
1931 |
-
return $this->IssuingDistributionPoint;
|
1932 |
-
case 'id-ce-freshestCRL':
|
1933 |
-
return $this->CRLDistributionPoints;
|
1934 |
-
case 'id-ce-cRLReasons':
|
1935 |
-
return $this->CRLReason;
|
1936 |
-
case 'id-ce-invalidityDate':
|
1937 |
-
return $this->InvalidityDate;
|
1938 |
-
case 'id-ce-certificateIssuer':
|
1939 |
-
return $this->CertificateIssuer;
|
1940 |
-
case 'id-ce-holdInstructionCode':
|
1941 |
-
return $this->HoldInstructionCode;
|
1942 |
-
case 'id-at-postalAddress':
|
1943 |
-
return $this->PostalAddress;
|
1944 |
-
}
|
1945 |
-
|
1946 |
-
return false;
|
1947 |
-
}
|
1948 |
-
|
1949 |
-
/**
|
1950 |
-
* Load an X.509 certificate as a certificate authority
|
1951 |
-
*
|
1952 |
-
* @param string $cert
|
1953 |
-
* @access public
|
1954 |
-
* @return bool
|
1955 |
-
*/
|
1956 |
-
function loadCA($cert)
|
1957 |
-
{
|
1958 |
-
$olddn = $this->dn;
|
1959 |
-
$oldcert = $this->currentCert;
|
1960 |
-
$oldsigsubj = $this->signatureSubject;
|
1961 |
-
$oldkeyid = $this->currentKeyIdentifier;
|
1962 |
-
|
1963 |
-
$cert = $this->loadX509($cert);
|
1964 |
-
if (!$cert) {
|
1965 |
-
$this->dn = $olddn;
|
1966 |
-
$this->currentCert = $oldcert;
|
1967 |
-
$this->signatureSubject = $oldsigsubj;
|
1968 |
-
$this->currentKeyIdentifier = $oldkeyid;
|
1969 |
-
|
1970 |
-
return false;
|
1971 |
-
}
|
1972 |
-
|
1973 |
-
/* From RFC5280 "PKIX Certificate and CRL Profile":
|
1974 |
-
|
1975 |
-
If the keyUsage extension is present, then the subject public key
|
1976 |
-
MUST NOT be used to verify signatures on certificates or CRLs unless
|
1977 |
-
the corresponding keyCertSign or cRLSign bit is set. */
|
1978 |
-
//$keyUsage = $this->getExtension('id-ce-keyUsage');
|
1979 |
-
//if ($keyUsage && !in_array('keyCertSign', $keyUsage)) {
|
1980 |
-
// return false;
|
1981 |
-
//}
|
1982 |
-
|
1983 |
-
/* From RFC5280 "PKIX Certificate and CRL Profile":
|
1984 |
-
|
1985 |
-
The cA boolean indicates whether the certified public key may be used
|
1986 |
-
to verify certificate signatures. If the cA boolean is not asserted,
|
1987 |
-
then the keyCertSign bit in the key usage extension MUST NOT be
|
1988 |
-
asserted. If the basic constraints extension is not present in a
|
1989 |
-
version 3 certificate, or the extension is present but the cA boolean
|
1990 |
-
is not asserted, then the certified public key MUST NOT be used to
|
1991 |
-
verify certificate signatures. */
|
1992 |
-
//$basicConstraints = $this->getExtension('id-ce-basicConstraints');
|
1993 |
-
//if (!$basicConstraints || !$basicConstraints['cA']) {
|
1994 |
-
// return false;
|
1995 |
-
//}
|
1996 |
-
|
1997 |
-
$this->CAs[] = $cert;
|
1998 |
-
|
1999 |
-
$this->dn = $olddn;
|
2000 |
-
$this->currentCert = $oldcert;
|
2001 |
-
$this->signatureSubject = $oldsigsubj;
|
2002 |
-
|
2003 |
-
return true;
|
2004 |
-
}
|
2005 |
-
|
2006 |
-
/**
|
2007 |
-
* Validate an X.509 certificate against a URL
|
2008 |
-
*
|
2009 |
-
* From RFC2818 "HTTP over TLS":
|
2010 |
-
*
|
2011 |
-
* Matching is performed using the matching rules specified by
|
2012 |
-
* [RFC2459]. If more than one identity of a given type is present in
|
2013 |
-
* the certificate (e.g., more than one dNSName name, a match in any one
|
2014 |
-
* of the set is considered acceptable.) Names may contain the wildcard
|
2015 |
-
* character * which is considered to match any single domain name
|
2016 |
-
* component or component fragment. E.g., *.a.com matches foo.a.com but
|
2017 |
-
* not bar.foo.a.com. f*.com matches foo.com but not bar.com.
|
2018 |
-
*
|
2019 |
-
* @param string $url
|
2020 |
-
* @access public
|
2021 |
-
* @return bool
|
2022 |
-
*/
|
2023 |
-
function validateURL($url)
|
2024 |
-
{
|
2025 |
-
if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) {
|
2026 |
-
return false;
|
2027 |
-
}
|
2028 |
-
|
2029 |
-
$components = parse_url($url);
|
2030 |
-
if (!isset($components['host'])) {
|
2031 |
-
return false;
|
2032 |
-
}
|
2033 |
-
|
2034 |
-
if ($names = $this->getExtension('id-ce-subjectAltName')) {
|
2035 |
-
foreach ($names as $name) {
|
2036 |
-
foreach ($name as $key => $value) {
|
2037 |
-
$value = str_replace(array('.', '*'), array('\.', '[^.]*'), $value);
|
2038 |
-
switch ($key) {
|
2039 |
-
case 'dNSName':
|
2040 |
-
/* From RFC2818 "HTTP over TLS":
|
2041 |
-
|
2042 |
-
If a subjectAltName extension of type dNSName is present, that MUST
|
2043 |
-
be used as the identity. Otherwise, the (most specific) Common Name
|
2044 |
-
field in the Subject field of the certificate MUST be used. Although
|
2045 |
-
the use of the Common Name is existing practice, it is deprecated and
|
2046 |
-
Certification Authorities are encouraged to use the dNSName instead. */
|
2047 |
-
if (preg_match('#^' . $value . '$#', $components['host'])) {
|
2048 |
-
return true;
|
2049 |
-
}
|
2050 |
-
break;
|
2051 |
-
case 'iPAddress':
|
2052 |
-
/* From RFC2818 "HTTP over TLS":
|
2053 |
-
|
2054 |
-
In some cases, the URI is specified as an IP address rather than a
|
2055 |
-
hostname. In this case, the iPAddress subjectAltName must be present
|
2056 |
-
in the certificate and must exactly match the IP in the URI. */
|
2057 |
-
if (preg_match('#(?:\d{1-3}\.){4}#', $components['host'] . '.') && preg_match('#^' . $value . '$#', $components['host'])) {
|
2058 |
-
return true;
|
2059 |
-
}
|
2060 |
-
}
|
2061 |
-
}
|
2062 |
-
}
|
2063 |
-
return false;
|
2064 |
-
}
|
2065 |
-
|
2066 |
-
if ($value = $this->getDNProp('id-at-commonName')) {
|
2067 |
-
$value = str_replace(array('.', '*'), array('\.', '[^.]*'), $value[0]);
|
2068 |
-
return preg_match('#^' . $value . '$#', $components['host']);
|
2069 |
-
}
|
2070 |
-
|
2071 |
-
return false;
|
2072 |
-
}
|
2073 |
-
|
2074 |
-
/**
|
2075 |
-
* Validate a date
|
2076 |
-
*
|
2077 |
-
* If $date isn't defined it is assumed to be the current date.
|
2078 |
-
*
|
2079 |
-
* @param int $date optional
|
2080 |
-
* @access public
|
2081 |
-
*/
|
2082 |
-
function validateDate($date = null)
|
2083 |
-
{
|
2084 |
-
if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) {
|
2085 |
-
return false;
|
2086 |
-
}
|
2087 |
-
|
2088 |
-
if (!isset($date)) {
|
2089 |
-
$date = new DateTime($date, new DateTimeZone(@date_default_timezone_get()));
|
2090 |
-
}
|
2091 |
-
|
2092 |
-
$notBefore = $this->currentCert['tbsCertificate']['validity']['notBefore'];
|
2093 |
-
$notBefore = isset($notBefore['generalTime']) ? $notBefore['generalTime'] : $notBefore['utcTime'];
|
2094 |
-
|
2095 |
-
$notAfter = $this->currentCert['tbsCertificate']['validity']['notAfter'];
|
2096 |
-
$notAfter = isset($notAfter['generalTime']) ? $notAfter['generalTime'] : $notAfter['utcTime'];
|
2097 |
-
|
2098 |
-
switch (true) {
|
2099 |
-
case $date < new DateTime($notBefore, new DateTimeZone(@date_default_timezone_get())):
|
2100 |
-
case $date > new DateTime($notAfter, new DateTimeZone(@date_default_timezone_get())):
|
2101 |
-
return false;
|
2102 |
-
}
|
2103 |
-
|
2104 |
-
return true;
|
2105 |
-
}
|
2106 |
-
|
2107 |
-
/**
|
2108 |
-
* Validate a signature
|
2109 |
-
*
|
2110 |
-
* Works on X.509 certs, CSR's and CRL's.
|
2111 |
-
* Returns true if the signature is verified, false if it is not correct or null on error
|
2112 |
-
*
|
2113 |
-
* By default returns false for self-signed certs. Call validateSignature(false) to make this support
|
2114 |
-
* self-signed.
|
2115 |
-
*
|
2116 |
-
* The behavior of this function is inspired by {@link http://php.net/openssl-verify openssl_verify}.
|
2117 |
-
*
|
2118 |
-
* @param bool $caonly optional
|
2119 |
-
* @access public
|
2120 |
-
* @return mixed
|
2121 |
-
*/
|
2122 |
-
function validateSignature($caonly = true)
|
2123 |
-
{
|
2124 |
-
if (!is_array($this->currentCert) || !isset($this->signatureSubject)) {
|
2125 |
-
return null;
|
2126 |
-
}
|
2127 |
-
|
2128 |
-
/* TODO:
|
2129 |
-
"emailAddress attribute values are not case-sensitive (e.g., "subscriber@example.com" is the same as "SUBSCRIBER@EXAMPLE.COM")."
|
2130 |
-
-- http://tools.ietf.org/html/rfc5280#section-4.1.2.6
|
2131 |
-
|
2132 |
-
implement pathLenConstraint in the id-ce-basicConstraints extension */
|
2133 |
-
|
2134 |
-
switch (true) {
|
2135 |
-
case isset($this->currentCert['tbsCertificate']):
|
2136 |
-
// self-signed cert
|
2137 |
-
switch (true) {
|
2138 |
-
case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertificate']['issuer'] === $this->currentCert['tbsCertificate']['subject']:
|
2139 |
-
case defined('FILE_X509_IGNORE_TYPE') && $this->getIssuerDN(self::DN_STRING) === $this->getDN(self::DN_STRING):
|
2140 |
-
$authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
|
2141 |
-
$subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier');
|
2142 |
-
switch (true) {
|
2143 |
-
case !is_array($authorityKey):
|
2144 |
-
case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
|
2145 |
-
$signingCert = $this->currentCert; // working cert
|
2146 |
-
}
|
2147 |
-
}
|
2148 |
-
|
2149 |
-
if (!empty($this->CAs)) {
|
2150 |
-
for ($i = 0; $i < count($this->CAs); $i++) {
|
2151 |
-
// even if the cert is a self-signed one we still want to see if it's a CA;
|
2152 |
-
// if not, we'll conditionally return an error
|
2153 |
-
$ca = $this->CAs[$i];
|
2154 |
-
switch (true) {
|
2155 |
-
case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertificate']['issuer'] === $ca['tbsCertificate']['subject']:
|
2156 |
-
case defined('FILE_X509_IGNORE_TYPE') && $this->getDN(self::DN_STRING, $this->currentCert['tbsCertificate']['issuer']) === $this->getDN(self::DN_STRING, $ca['tbsCertificate']['subject']):
|
2157 |
-
$authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
|
2158 |
-
$subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
|
2159 |
-
switch (true) {
|
2160 |
-
case !is_array($authorityKey):
|
2161 |
-
case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
|
2162 |
-
$signingCert = $ca; // working cert
|
2163 |
-
break 3;
|
2164 |
-
}
|
2165 |
-
}
|
2166 |
-
}
|
2167 |
-
if (count($this->CAs) == $i && $caonly) {
|
2168 |
-
return false;
|
2169 |
-
}
|
2170 |
-
} elseif (!isset($signingCert) || $caonly) {
|
2171 |
-
return false;
|
2172 |
-
}
|
2173 |
-
return $this->_validateSignature(
|
2174 |
-
$signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'],
|
2175 |
-
$signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'],
|
2176 |
-
$this->currentCert['signatureAlgorithm']['algorithm'],
|
2177 |
-
substr(base64_decode($this->currentCert['signature']), 1),
|
2178 |
-
$this->signatureSubject
|
2179 |
-
);
|
2180 |
-
case isset($this->currentCert['certificationRequestInfo']):
|
2181 |
-
return $this->_validateSignature(
|
2182 |
-
$this->currentCert['certificationRequestInfo']['subjectPKInfo']['algorithm']['algorithm'],
|
2183 |
-
$this->currentCert['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'],
|
2184 |
-
$this->currentCert['signatureAlgorithm']['algorithm'],
|
2185 |
-
substr(base64_decode($this->currentCert['signature']), 1),
|
2186 |
-
$this->signatureSubject
|
2187 |
-
);
|
2188 |
-
case isset($this->currentCert['publicKeyAndChallenge']):
|
2189 |
-
return $this->_validateSignature(
|
2190 |
-
$this->currentCert['publicKeyAndChallenge']['spki']['algorithm']['algorithm'],
|
2191 |
-
$this->currentCert['publicKeyAndChallenge']['spki']['subjectPublicKey'],
|
2192 |
-
$this->currentCert['signatureAlgorithm']['algorithm'],
|
2193 |
-
substr(base64_decode($this->currentCert['signature']), 1),
|
2194 |
-
$this->signatureSubject
|
2195 |
-
);
|
2196 |
-
case isset($this->currentCert['tbsCertList']):
|
2197 |
-
if (!empty($this->CAs)) {
|
2198 |
-
for ($i = 0; $i < count($this->CAs); $i++) {
|
2199 |
-
$ca = $this->CAs[$i];
|
2200 |
-
switch (true) {
|
2201 |
-
case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertList']['issuer'] === $ca['tbsCertificate']['subject']:
|
2202 |
-
case defined('FILE_X509_IGNORE_TYPE') && $this->getDN(self::DN_STRING, $this->currentCert['tbsCertList']['issuer']) === $this->getDN(self::DN_STRING, $ca['tbsCertificate']['subject']):
|
2203 |
-
$authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
|
2204 |
-
$subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
|
2205 |
-
switch (true) {
|
2206 |
-
case !is_array($authorityKey):
|
2207 |
-
case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
|
2208 |
-
$signingCert = $ca; // working cert
|
2209 |
-
break 3;
|
2210 |
-
}
|
2211 |
-
}
|
2212 |
-
}
|
2213 |
-
}
|
2214 |
-
if (!isset($signingCert)) {
|
2215 |
-
return false;
|
2216 |
-
}
|
2217 |
-
return $this->_validateSignature(
|
2218 |
-
$signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'],
|
2219 |
-
$signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'],
|
2220 |
-
$this->currentCert['signatureAlgorithm']['algorithm'],
|
2221 |
-
substr(base64_decode($this->currentCert['signature']), 1),
|
2222 |
-
$this->signatureSubject
|
2223 |
-
);
|
2224 |
-
default:
|
2225 |
-
return false;
|
2226 |
-
}
|
2227 |
-
}
|
2228 |
-
|
2229 |
-
/**
|
2230 |
-
* Validates a signature
|
2231 |
-
*
|
2232 |
-
* Returns true if the signature is verified, false if it is not correct or null on error
|
2233 |
-
*
|
2234 |
-
* @param string $publicKeyAlgorithm
|
2235 |
-
* @param string $publicKey
|
2236 |
-
* @param string $signatureAlgorithm
|
2237 |
-
* @param string $signature
|
2238 |
-
* @param string $signatureSubject
|
2239 |
-
* @access private
|
2240 |
-
* @return int
|
2241 |
-
*/
|
2242 |
-
function _validateSignature($publicKeyAlgorithm, $publicKey, $signatureAlgorithm, $signature, $signatureSubject)
|
2243 |
-
{
|
2244 |
-
switch ($publicKeyAlgorithm) {
|
2245 |
-
case 'rsaEncryption':
|
2246 |
-
$rsa = new RSA();
|
2247 |
-
$rsa->loadKey($publicKey);
|
2248 |
-
|
2249 |
-
switch ($signatureAlgorithm) {
|
2250 |
-
case 'md2WithRSAEncryption':
|
2251 |
-
case 'md5WithRSAEncryption':
|
2252 |
-
case 'sha1WithRSAEncryption':
|
2253 |
-
case 'sha224WithRSAEncryption':
|
2254 |
-
case 'sha256WithRSAEncryption':
|
2255 |
-
case 'sha384WithRSAEncryption':
|
2256 |
-
case 'sha512WithRSAEncryption':
|
2257 |
-
$rsa->setHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm));
|
2258 |
-
$rsa->setSignatureMode(RSA::SIGNATURE_PKCS1);
|
2259 |
-
if (!@$rsa->verify($signatureSubject, $signature)) {
|
2260 |
-
return false;
|
2261 |
-
}
|
2262 |
-
break;
|
2263 |
-
default:
|
2264 |
-
return null;
|
2265 |
-
}
|
2266 |
-
break;
|
2267 |
-
default:
|
2268 |
-
return null;
|
2269 |
-
}
|
2270 |
-
|
2271 |
-
return true;
|
2272 |
-
}
|
2273 |
-
|
2274 |
-
/**
|
2275 |
-
* Reformat public keys
|
2276 |
-
*
|
2277 |
-
* Reformats a public key to a format supported by phpseclib (if applicable)
|
2278 |
-
*
|
2279 |
-
* @param string $algorithm
|
2280 |
-
* @param string $key
|
2281 |
-
* @access private
|
2282 |
-
* @return string
|
2283 |
-
*/
|
2284 |
-
function _reformatKey($algorithm, $key)
|
2285 |
-
{
|
2286 |
-
switch ($algorithm) {
|
2287 |
-
case 'rsaEncryption':
|
2288 |
-
return
|
2289 |
-
"-----BEGIN RSA PUBLIC KEY-----\r\n" .
|
2290 |
-
// subjectPublicKey is stored as a bit string in X.509 certs. the first byte of a bit string represents how many bits
|
2291 |
-
// in the last byte should be ignored. the following only supports non-zero stuff but as none of the X.509 certs Firefox
|
2292 |
-
// uses as a cert authority actually use a non-zero bit I think it's safe to assume that none do.
|
2293 |
-
chunk_split(base64_encode(substr(base64_decode($key), 1)), 64) .
|
2294 |
-
'-----END RSA PUBLIC KEY-----';
|
2295 |
-
default:
|
2296 |
-
return $key;
|
2297 |
-
}
|
2298 |
-
}
|
2299 |
-
|
2300 |
-
/**
|
2301 |
-
* Decodes an IP address
|
2302 |
-
*
|
2303 |
-
* Takes in a base64 encoded "blob" and returns a human readable IP address
|
2304 |
-
*
|
2305 |
-
* @param string $ip
|
2306 |
-
* @access private
|
2307 |
-
* @return string
|
2308 |
-
*/
|
2309 |
-
function _decodeIP($ip)
|
2310 |
-
{
|
2311 |
-
return inet_ntop(base64_decode($ip));
|
2312 |
-
}
|
2313 |
-
|
2314 |
-
/**
|
2315 |
-
* Encodes an IP address
|
2316 |
-
*
|
2317 |
-
* Takes a human readable IP address into a base64-encoded "blob"
|
2318 |
-
*
|
2319 |
-
* @param string $ip
|
2320 |
-
* @access private
|
2321 |
-
* @return string
|
2322 |
-
*/
|
2323 |
-
function _encodeIP($ip)
|
2324 |
-
{
|
2325 |
-
return base64_encode(inet_pton($ip));
|
2326 |
-
}
|
2327 |
-
|
2328 |
-
/**
|
2329 |
-
* "Normalizes" a Distinguished Name property
|
2330 |
-
*
|
2331 |
-
* @param string $propName
|
2332 |
-
* @access private
|
2333 |
-
* @return mixed
|
2334 |
-
*/
|
2335 |
-
function _translateDNProp($propName)
|
2336 |
-
{
|
2337 |
-
switch (strtolower($propName)) {
|
2338 |
-
case 'id-at-countryname':
|
2339 |
-
case 'countryname':
|
2340 |
-
case 'c':
|
2341 |
-
return 'id-at-countryName';
|
2342 |
-
case 'id-at-organizationname':
|
2343 |
-
case 'organizationname':
|
2344 |
-
case 'o':
|
2345 |
-
return 'id-at-organizationName';
|
2346 |
-
case 'id-at-dnqualifier':
|
2347 |
-
case 'dnqualifier':
|
2348 |
-
return 'id-at-dnQualifier';
|
2349 |
-
case 'id-at-commonname':
|
2350 |
-
case 'commonname':
|
2351 |
-
case 'cn':
|
2352 |
-
return 'id-at-commonName';
|
2353 |
-
case 'id-at-stateorprovincename':
|
2354 |
-
case 'stateorprovincename':
|
2355 |
-
case 'state':
|
2356 |
-
case 'province':
|
2357 |
-
case 'provincename':
|
2358 |
-
case 'st':
|
2359 |
-
return 'id-at-stateOrProvinceName';
|
2360 |
-
case 'id-at-localityname':
|
2361 |
-
case 'localityname':
|
2362 |
-
case 'l':
|
2363 |
-
return 'id-at-localityName';
|
2364 |
-
case 'id-emailaddress':
|
2365 |
-
case 'emailaddress':
|
2366 |
-
return 'pkcs-9-at-emailAddress';
|
2367 |
-
case 'id-at-serialnumber':
|
2368 |
-
case 'serialnumber':
|
2369 |
-
return 'id-at-serialNumber';
|
2370 |
-
case 'id-at-postalcode':
|
2371 |
-
case 'postalcode':
|
2372 |
-
return 'id-at-postalCode';
|
2373 |
-
case 'id-at-streetaddress':
|
2374 |
-
case 'streetaddress':
|
2375 |
-
return 'id-at-streetAddress';
|
2376 |
-
case 'id-at-name':
|
2377 |
-
case 'name':
|
2378 |
-
return 'id-at-name';
|
2379 |
-
case 'id-at-givenname':
|
2380 |
-
case 'givenname':
|
2381 |
-
return 'id-at-givenName';
|
2382 |
-
case 'id-at-surname':
|
2383 |
-
case 'surname':
|
2384 |
-
case 'sn':
|
2385 |
-
return 'id-at-surname';
|
2386 |
-
case 'id-at-initials':
|
2387 |
-
case 'initials':
|
2388 |
-
return 'id-at-initials';
|
2389 |
-
case 'id-at-generationqualifier':
|
2390 |
-
case 'generationqualifier':
|
2391 |
-
return 'id-at-generationQualifier';
|
2392 |
-
case 'id-at-organizationalunitname':
|
2393 |
-
case 'organizationalunitname':
|
2394 |
-
case 'ou':
|
2395 |
-
return 'id-at-organizationalUnitName';
|
2396 |
-
case 'id-at-pseudonym':
|
2397 |
-
case 'pseudonym':
|
2398 |
-
return 'id-at-pseudonym';
|
2399 |
-
case 'id-at-title':
|
2400 |
-
case 'title':
|
2401 |
-
return 'id-at-title';
|
2402 |
-
case 'id-at-description':
|
2403 |
-
case 'description':
|
2404 |
-
return 'id-at-description';
|
2405 |
-
case 'id-at-role':
|
2406 |
-
case 'role':
|
2407 |
-
return 'id-at-role';
|
2408 |
-
case 'id-at-uniqueidentifier':
|
2409 |
-
case 'uniqueidentifier':
|
2410 |
-
case 'x500uniqueidentifier':
|
2411 |
-
return 'id-at-uniqueIdentifier';
|
2412 |
-
case 'postaladdress':
|
2413 |
-
case 'id-at-postaladdress':
|
2414 |
-
return 'id-at-postalAddress';
|
2415 |
-
default:
|
2416 |
-
return false;
|
2417 |
-
}
|
2418 |
-
}
|
2419 |
-
|
2420 |
-
/**
|
2421 |
-
* Set a Distinguished Name property
|
2422 |
-
*
|
2423 |
-
* @param string $propName
|
2424 |
-
* @param mixed $propValue
|
2425 |
-
* @param string $type optional
|
2426 |
-
* @access public
|
2427 |
-
* @return bool
|
2428 |
-
*/
|
2429 |
-
function setDNProp($propName, $propValue, $type = 'utf8String')
|
2430 |
-
{
|
2431 |
-
if (empty($this->dn)) {
|
2432 |
-
$this->dn = array('rdnSequence' => array());
|
2433 |
-
}
|
2434 |
-
|
2435 |
-
if (($propName = $this->_translateDNProp($propName)) === false) {
|
2436 |
-
return false;
|
2437 |
-
}
|
2438 |
-
|
2439 |
-
foreach ((array) $propValue as $v) {
|
2440 |
-
if (!is_array($v) && isset($type)) {
|
2441 |
-
$v = array($type => $v);
|
2442 |
-
}
|
2443 |
-
$this->dn['rdnSequence'][] = array(
|
2444 |
-
array(
|
2445 |
-
'type' => $propName,
|
2446 |
-
'value'=> $v
|
2447 |
-
)
|
2448 |
-
);
|
2449 |
-
}
|
2450 |
-
|
2451 |
-
return true;
|
2452 |
-
}
|
2453 |
-
|
2454 |
-
/**
|
2455 |
-
* Remove Distinguished Name properties
|
2456 |
-
*
|
2457 |
-
* @param string $propName
|
2458 |
-
* @access public
|
2459 |
-
*/
|
2460 |
-
function removeDNProp($propName)
|
2461 |
-
{
|
2462 |
-
if (empty($this->dn)) {
|
2463 |
-
return;
|
2464 |
-
}
|
2465 |
-
|
2466 |
-
if (($propName = $this->_translateDNProp($propName)) === false) {
|
2467 |
-
return;
|
2468 |
-
}
|
2469 |
-
|
2470 |
-
$dn = &$this->dn['rdnSequence'];
|
2471 |
-
$size = count($dn);
|
2472 |
-
for ($i = 0; $i < $size; $i++) {
|
2473 |
-
if ($dn[$i][0]['type'] == $propName) {
|
2474 |
-
unset($dn[$i]);
|
2475 |
-
}
|
2476 |
-
}
|
2477 |
-
|
2478 |
-
$dn = array_values($dn);
|
2479 |
-
}
|
2480 |
-
|
2481 |
-
/**
|
2482 |
-
* Get Distinguished Name properties
|
2483 |
-
*
|
2484 |
-
* @param string $propName
|
2485 |
-
* @param array $dn optional
|
2486 |
-
* @param bool $withType optional
|
2487 |
-
* @return mixed
|
2488 |
-
* @access public
|
2489 |
-
*/
|
2490 |
-
function getDNProp($propName, $dn = null, $withType = false)
|
2491 |
-
{
|
2492 |
-
if (!isset($dn)) {
|
2493 |
-
$dn = $this->dn;
|
2494 |
-
}
|
2495 |
-
|
2496 |
-
if (empty($dn)) {
|
2497 |
-
return false;
|
2498 |
-
}
|
2499 |
-
|
2500 |
-
if (($propName = $this->_translateDNProp($propName)) === false) {
|
2501 |
-
return false;
|
2502 |
-
}
|
2503 |
-
|
2504 |
-
$asn1 = new ASN1();
|
2505 |
-
$asn1->loadOIDs($this->oids);
|
2506 |
-
$filters = array();
|
2507 |
-
$filters['value'] = array('type' => ASN1::TYPE_UTF8_STRING);
|
2508 |
-
$asn1->loadFilters($filters);
|
2509 |
-
$this->_mapOutDNs($dn, 'rdnSequence', $asn1);
|
2510 |
-
$dn = $dn['rdnSequence'];
|
2511 |
-
$result = array();
|
2512 |
-
for ($i = 0; $i < count($dn); $i++) {
|
2513 |
-
if ($dn[$i][0]['type'] == $propName) {
|
2514 |
-
$v = $dn[$i][0]['value'];
|
2515 |
-
if (!$withType) {
|
2516 |
-
if (is_array($v)) {
|
2517 |
-
foreach ($v as $type => $s) {
|
2518 |
-
$type = array_search($type, $asn1->ANYmap, true);
|
2519 |
-
if ($type !== false && isset($asn1->stringTypeSize[$type])) {
|
2520 |
-
$s = $asn1->convert($s, $type);
|
2521 |
-
if ($s !== false) {
|
2522 |
-
$v = $s;
|
2523 |
-
break;
|
2524 |
-
}
|
2525 |
-
}
|
2526 |
-
}
|
2527 |
-
if (is_array($v)) {
|
2528 |
-
$v = array_pop($v); // Always strip data type.
|
2529 |
-
}
|
2530 |
-
} elseif (is_object($v) && $v instanceof Element) {
|
2531 |
-
$map = $this->_getMapping($propName);
|
2532 |
-
if (!is_bool($map)) {
|
2533 |
-
$decoded = $asn1->decodeBER($v);
|
2534 |
-
$v = $asn1->asn1map($decoded[0], $map);
|
2535 |
-
}
|
2536 |
-
}
|
2537 |
-
}
|
2538 |
-
$result[] = $v;
|
2539 |
-
}
|
2540 |
-
}
|
2541 |
-
|
2542 |
-
return $result;
|
2543 |
-
}
|
2544 |
-
|
2545 |
-
/**
|
2546 |
-
* Set a Distinguished Name
|
2547 |
-
*
|
2548 |
-
* @param mixed $dn
|
2549 |
-
* @param bool $merge optional
|
2550 |
-
* @param string $type optional
|
2551 |
-
* @access public
|
2552 |
-
* @return bool
|
2553 |
-
*/
|
2554 |
-
function setDN($dn, $merge = false, $type = 'utf8String')
|
2555 |
-
{
|
2556 |
-
if (!$merge) {
|
2557 |
-
$this->dn = null;
|
2558 |
-
}
|
2559 |
-
|
2560 |
-
if (is_array($dn)) {
|
2561 |
-
if (isset($dn['rdnSequence'])) {
|
2562 |
-
$this->dn = $dn; // No merge here.
|
2563 |
-
return true;
|
2564 |
-
}
|
2565 |
-
|
2566 |
-
// handles stuff generated by openssl_x509_parse()
|
2567 |
-
foreach ($dn as $prop => $value) {
|
2568 |
-
if (!$this->setDNProp($prop, $value, $type)) {
|
2569 |
-
return false;
|
2570 |
-
}
|
2571 |
-
}
|
2572 |
-
return true;
|
2573 |
-
}
|
2574 |
-
|
2575 |
-
// handles everything else
|
2576 |
-
$results = preg_split('#((?:^|, *|/)(?:C=|O=|OU=|CN=|L=|ST=|SN=|postalCode=|streetAddress=|emailAddress=|serialNumber=|organizationalUnitName=|title=|description=|role=|x500UniqueIdentifier=|postalAddress=))#', $dn, -1, PREG_SPLIT_DELIM_CAPTURE);
|
2577 |
-
for ($i = 1; $i < count($results); $i+=2) {
|
2578 |
-
$prop = trim($results[$i], ', =/');
|
2579 |
-
$value = $results[$i + 1];
|
2580 |
-
if (!$this->setDNProp($prop, $value, $type)) {
|
2581 |
-
return false;
|
2582 |
-
}
|
2583 |
-
}
|
2584 |
-
|
2585 |
-
return true;
|
2586 |
-
}
|
2587 |
-
|
2588 |
-
/**
|
2589 |
-
* Get the Distinguished Name for a certificates subject
|
2590 |
-
*
|
2591 |
-
* @param mixed $format optional
|
2592 |
-
* @param array $dn optional
|
2593 |
-
* @access public
|
2594 |
-
* @return bool
|
2595 |
-
*/
|
2596 |
-
function getDN($format = self::DN_ARRAY, $dn = null)
|
2597 |
-
{
|
2598 |
-
if (!isset($dn)) {
|
2599 |
-
$dn = isset($this->currentCert['tbsCertList']) ? $this->currentCert['tbsCertList']['issuer'] : $this->dn;
|
2600 |
-
}
|
2601 |
-
|
2602 |
-
switch ((int) $format) {
|
2603 |
-
case self::DN_ARRAY:
|
2604 |
-
return $dn;
|
2605 |
-
case self::DN_ASN1:
|
2606 |
-
$asn1 = new ASN1();
|
2607 |
-
$asn1->loadOIDs($this->oids);
|
2608 |
-
$filters = array();
|
2609 |
-
$filters['rdnSequence']['value'] = array('type' => ASN1::TYPE_UTF8_STRING);
|
2610 |
-
$asn1->loadFilters($filters);
|
2611 |
-
$this->_mapOutDNs($dn, 'rdnSequence', $asn1);
|
2612 |
-
return $asn1->encodeDER($dn, $this->Name);
|
2613 |
-
case self::DN_CANON:
|
2614 |
-
// No SEQUENCE around RDNs and all string values normalized as
|
2615 |
-
// trimmed lowercase UTF-8 with all spacing as one blank.
|
2616 |
-
// constructed RDNs will not be canonicalized
|
2617 |
-
$asn1 = new ASN1();
|
2618 |
-
$asn1->loadOIDs($this->oids);
|
2619 |
-
$filters = array();
|
2620 |
-
$filters['value'] = array('type' => ASN1::TYPE_UTF8_STRING);
|
2621 |
-
$asn1->loadFilters($filters);
|
2622 |
-
$result = '';
|
2623 |
-
$this->_mapOutDNs($dn, 'rdnSequence', $asn1);
|
2624 |
-
foreach ($dn['rdnSequence'] as $rdn) {
|
2625 |
-
foreach ($rdn as $i => $attr) {
|
2626 |
-
$attr = &$rdn[$i];
|
2627 |
-
if (is_array($attr['value'])) {
|
2628 |
-
foreach ($attr['value'] as $type => $v) {
|
2629 |
-
$type = array_search($type, $asn1->ANYmap, true);
|
2630 |
-
if ($type !== false && isset($asn1->stringTypeSize[$type])) {
|
2631 |
-
$v = $asn1->convert($v, $type);
|
2632 |
-
if ($v !== false) {
|
2633 |
-
$v = preg_replace('/\s+/', ' ', $v);
|
2634 |
-
$attr['value'] = strtolower(trim($v));
|
2635 |
-
break;
|
2636 |
-
}
|
2637 |
-
}
|
2638 |
-
}
|
2639 |
-
}
|
2640 |
-
}
|
2641 |
-
$result .= $asn1->encodeDER($rdn, $this->RelativeDistinguishedName);
|
2642 |
-
}
|
2643 |
-
return $result;
|
2644 |
-
case self::DN_HASH:
|
2645 |
-
$dn = $this->getDN(self::DN_CANON, $dn);
|
2646 |
-
$hash = new Hash('sha1');
|
2647 |
-
$hash = $hash->hash($dn);
|
2648 |
-
extract(unpack('Vhash', $hash));
|
2649 |
-
return strtolower(bin2hex(pack('N', $hash)));
|
2650 |
-
}
|
2651 |
-
|
2652 |
-
// Default is to return a string.
|
2653 |
-
$start = true;
|
2654 |
-
$output = '';
|
2655 |
-
|
2656 |
-
$result = array();
|
2657 |
-
$asn1 = new ASN1();
|
2658 |
-
$asn1->loadOIDs($this->oids);
|
2659 |
-
$filters = array();
|
2660 |
-
$filters['rdnSequence']['value'] = array('type' => ASN1::TYPE_UTF8_STRING);
|
2661 |
-
$asn1->loadFilters($filters);
|
2662 |
-
$this->_mapOutDNs($dn, 'rdnSequence', $asn1);
|
2663 |
-
|
2664 |
-
foreach ($dn['rdnSequence'] as $field) {
|
2665 |
-
$prop = $field[0]['type'];
|
2666 |
-
$value = $field[0]['value'];
|
2667 |
-
|
2668 |
-
$delim = ', ';
|
2669 |
-
switch ($prop) {
|
2670 |
-
case 'id-at-countryName':
|
2671 |
-
$desc = 'C';
|
2672 |
-
break;
|
2673 |
-
case 'id-at-stateOrProvinceName':
|
2674 |
-
$desc = 'ST';
|
2675 |
-
break;
|
2676 |
-
case 'id-at-organizationName':
|
2677 |
-
$desc = 'O';
|
2678 |
-
break;
|
2679 |
-
case 'id-at-organizationalUnitName':
|
2680 |
-
$desc = 'OU';
|
2681 |
-
break;
|
2682 |
-
case 'id-at-commonName':
|
2683 |
-
$desc = 'CN';
|
2684 |
-
break;
|
2685 |
-
case 'id-at-localityName':
|
2686 |
-
$desc = 'L';
|
2687 |
-
break;
|
2688 |
-
case 'id-at-surname':
|
2689 |
-
$desc = 'SN';
|
2690 |
-
break;
|
2691 |
-
case 'id-at-uniqueIdentifier':
|
2692 |
-
$delim = '/';
|
2693 |
-
$desc = 'x500UniqueIdentifier';
|
2694 |
-
break;
|
2695 |
-
case 'id-at-postalAddress':
|
2696 |
-
$delim = '/';
|
2697 |
-
$desc = 'postalAddress';
|
2698 |
-
break;
|
2699 |
-
default:
|
2700 |
-
$delim = '/';
|
2701 |
-
$desc = preg_replace('#.+-([^-]+)$#', '$1', $prop);
|
2702 |
-
}
|
2703 |
-
|
2704 |
-
if (!$start) {
|
2705 |
-
$output.= $delim;
|
2706 |
-
}
|
2707 |
-
if (is_array($value)) {
|
2708 |
-
foreach ($value as $type => $v) {
|
2709 |
-
$type = array_search($type, $asn1->ANYmap, true);
|
2710 |
-
if ($type !== false && isset($asn1->stringTypeSize[$type])) {
|
2711 |
-
$v = $asn1->convert($v, $type);
|
2712 |
-
if ($v !== false) {
|
2713 |
-
$value = $v;
|
2714 |
-
break;
|
2715 |
-
}
|
2716 |
-
}
|
2717 |
-
}
|
2718 |
-
if (is_array($value)) {
|
2719 |
-
$value = array_pop($value); // Always strip data type.
|
2720 |
-
}
|
2721 |
-
} elseif (is_object($value) && $value instanceof Element) {
|
2722 |
-
$callback = create_function('$x', 'return "\x" . bin2hex($x[0]);');
|
2723 |
-
$value = strtoupper(preg_replace_callback('#[^\x20-\x7E]#', $callback, $value->element));
|
2724 |
-
}
|
2725 |
-
$output.= $desc . '=' . $value;
|
2726 |
-
$result[$desc] = isset($result[$desc]) ?
|
2727 |
-
array_merge((array) $dn[$prop], array($value)) :
|
2728 |
-
$value;
|
2729 |
-
$start = false;
|
2730 |
-
}
|
2731 |
-
|
2732 |
-
return $format == self::DN_OPENSSL ? $result : $output;
|
2733 |
-
}
|
2734 |
-
|
2735 |
-
/**
|
2736 |
-
* Get the Distinguished Name for a certificate/crl issuer
|
2737 |
-
*
|
2738 |
-
* @param int $format optional
|
2739 |
-
* @access public
|
2740 |
-
* @return mixed
|
2741 |
-
*/
|
2742 |
-
function getIssuerDN($format = self::DN_ARRAY)
|
2743 |
-
{
|
2744 |
-
switch (true) {
|
2745 |
-
case !isset($this->currentCert) || !is_array($this->currentCert):
|
2746 |
-
break;
|
2747 |
-
case isset($this->currentCert['tbsCertificate']):
|
2748 |
-
return $this->getDN($format, $this->currentCert['tbsCertificate']['issuer']);
|
2749 |
-
case isset($this->currentCert['tbsCertList']):
|
2750 |
-
return $this->getDN($format, $this->currentCert['tbsCertList']['issuer']);
|
2751 |
-
}
|
2752 |
-
|
2753 |
-
return false;
|
2754 |
-
}
|
2755 |
-
|
2756 |
-
/**
|
2757 |
-
* Get the Distinguished Name for a certificate/csr subject
|
2758 |
-
* Alias of getDN()
|
2759 |
-
*
|
2760 |
-
* @param int $format optional
|
2761 |
-
* @access public
|
2762 |
-
* @return mixed
|
2763 |
-
*/
|
2764 |
-
function getSubjectDN($format = self::DN_ARRAY)
|
2765 |
-
{
|
2766 |
-
switch (true) {
|
2767 |
-
case !empty($this->dn):
|
2768 |
-
return $this->getDN($format);
|
2769 |
-
case !isset($this->currentCert) || !is_array($this->currentCert):
|
2770 |
-
break;
|
2771 |
-
case isset($this->currentCert['tbsCertificate']):
|
2772 |
-
return $this->getDN($format, $this->currentCert['tbsCertificate']['subject']);
|
2773 |
-
case isset($this->currentCert['certificationRequestInfo']):
|
2774 |
-
return $this->getDN($format, $this->currentCert['certificationRequestInfo']['subject']);
|
2775 |
-
}
|
2776 |
-
|
2777 |
-
return false;
|
2778 |
-
}
|
2779 |
-
|
2780 |
-
/**
|
2781 |
-
* Get an individual Distinguished Name property for a certificate/crl issuer
|
2782 |
-
*
|
2783 |
-
* @param string $propName
|
2784 |
-
* @param bool $withType optional
|
2785 |
-
* @access public
|
2786 |
-
* @return mixed
|
2787 |
-
*/
|
2788 |
-
function getIssuerDNProp($propName, $withType = false)
|
2789 |
-
{
|
2790 |
-
switch (true) {
|
2791 |
-
case !isset($this->currentCert) || !is_array($this->currentCert):
|
2792 |
-
break;
|
2793 |
-
case isset($this->currentCert['tbsCertificate']):
|
2794 |
-
return $this->getDNProp($propName, $this->currentCert['tbsCertificate']['issuer'], $withType);
|
2795 |
-
case isset($this->currentCert['tbsCertList']):
|
2796 |
-
return $this->getDNProp($propName, $this->currentCert['tbsCertList']['issuer'], $withType);
|
2797 |
-
}
|
2798 |
-
|
2799 |
-
return false;
|
2800 |
-
}
|
2801 |
-
|
2802 |
-
/**
|
2803 |
-
* Get an individual Distinguished Name property for a certificate/csr subject
|
2804 |
-
*
|
2805 |
-
* @param string $propName
|
2806 |
-
* @param bool $withType optional
|
2807 |
-
* @access public
|
2808 |
-
* @return mixed
|
2809 |
-
*/
|
2810 |
-
function getSubjectDNProp($propName, $withType = false)
|
2811 |
-
{
|
2812 |
-
switch (true) {
|
2813 |
-
case !empty($this->dn):
|
2814 |
-
return $this->getDNProp($propName, null, $withType);
|
2815 |
-
case !isset($this->currentCert) || !is_array($this->currentCert):
|
2816 |
-
break;
|
2817 |
-
case isset($this->currentCert['tbsCertificate']):
|
2818 |
-
return $this->getDNProp($propName, $this->currentCert['tbsCertificate']['subject'], $withType);
|
2819 |
-
case isset($this->currentCert['certificationRequestInfo']):
|
2820 |
-
return $this->getDNProp($propName, $this->currentCert['certificationRequestInfo']['subject'], $withType);
|
2821 |
-
}
|
2822 |
-
|
2823 |
-
return false;
|
2824 |
-
}
|
2825 |
-
|
2826 |
-
/**
|
2827 |
-
* Get the certificate chain for the current cert
|
2828 |
-
*
|
2829 |
-
* @access public
|
2830 |
-
* @return mixed
|
2831 |
-
*/
|
2832 |
-
function getChain()
|
2833 |
-
{
|
2834 |
-
$chain = array($this->currentCert);
|
2835 |
-
|
2836 |
-
if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) {
|
2837 |
-
return false;
|
2838 |
-
}
|
2839 |
-
if (empty($this->CAs)) {
|
2840 |
-
return $chain;
|
2841 |
-
}
|
2842 |
-
while (true) {
|
2843 |
-
$currentCert = $chain[count($chain) - 1];
|
2844 |
-
for ($i = 0; $i < count($this->CAs); $i++) {
|
2845 |
-
$ca = $this->CAs[$i];
|
2846 |
-
if ($currentCert['tbsCertificate']['issuer'] === $ca['tbsCertificate']['subject']) {
|
2847 |
-
$authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier', $currentCert);
|
2848 |
-
$subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
|
2849 |
-
switch (true) {
|
2850 |
-
case !is_array($authorityKey):
|
2851 |
-
case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
|
2852 |
-
if ($currentCert === $ca) {
|
2853 |
-
break 3;
|
2854 |
-
}
|
2855 |
-
$chain[] = $ca;
|
2856 |
-
break 2;
|
2857 |
-
}
|
2858 |
-
}
|
2859 |
-
}
|
2860 |
-
if ($i == count($this->CAs)) {
|
2861 |
-
break;
|
2862 |
-
}
|
2863 |
-
}
|
2864 |
-
foreach ($chain as $key => $value) {
|
2865 |
-
$chain[$key] = new X509();
|
2866 |
-
$chain[$key]->loadX509($value);
|
2867 |
-
}
|
2868 |
-
return $chain;
|
2869 |
-
}
|
2870 |
-
|
2871 |
-
/**
|
2872 |
-
* Set public key
|
2873 |
-
*
|
2874 |
-
* Key needs to be a \phpseclib\Crypt\RSA object
|
2875 |
-
*
|
2876 |
-
* @param object $key
|
2877 |
-
* @access public
|
2878 |
-
* @return bool
|
2879 |
-
*/
|
2880 |
-
function setPublicKey($key)
|
2881 |
-
{
|
2882 |
-
$key->setPublicKey();
|
2883 |
-
$this->publicKey = $key;
|
2884 |
-
}
|
2885 |
-
|
2886 |
-
/**
|
2887 |
-
* Set private key
|
2888 |
-
*
|
2889 |
-
* Key needs to be a \phpseclib\Crypt\RSA object
|
2890 |
-
*
|
2891 |
-
* @param object $key
|
2892 |
-
* @access public
|
2893 |
-
*/
|
2894 |
-
function setPrivateKey($key)
|
2895 |
-
{
|
2896 |
-
$this->privateKey = $key;
|
2897 |
-
}
|
2898 |
-
|
2899 |
-
/**
|
2900 |
-
* Set challenge
|
2901 |
-
*
|
2902 |
-
* Used for SPKAC CSR's
|
2903 |
-
*
|
2904 |
-
* @param string $challenge
|
2905 |
-
* @access public
|
2906 |
-
*/
|
2907 |
-
function setChallenge($challenge)
|
2908 |
-
{
|
2909 |
-
$this->challenge = $challenge;
|
2910 |
-
}
|
2911 |
-
|
2912 |
-
/**
|
2913 |
-
* Gets the public key
|
2914 |
-
*
|
2915 |
-
* Returns a \phpseclib\Crypt\RSA object or a false.
|
2916 |
-
*
|
2917 |
-
* @access public
|
2918 |
-
* @return mixed
|
2919 |
-
*/
|
2920 |
-
function getPublicKey()
|
2921 |
-
{
|
2922 |
-
if (isset($this->publicKey)) {
|
2923 |
-
return $this->publicKey;
|
2924 |
-
}
|
2925 |
-
|
2926 |
-
if (isset($this->currentCert) && is_array($this->currentCert)) {
|
2927 |
-
foreach (array('tbsCertificate/subjectPublicKeyInfo', 'certificationRequestInfo/subjectPKInfo') as $path) {
|
2928 |
-
$keyinfo = $this->_subArray($this->currentCert, $path);
|
2929 |
-
if (!empty($keyinfo)) {
|
2930 |
-
break;
|
2931 |
-
}
|
2932 |
-
}
|
2933 |
-
}
|
2934 |
-
if (empty($keyinfo)) {
|
2935 |
-
return false;
|
2936 |
-
}
|
2937 |
-
|
2938 |
-
$key = $keyinfo['subjectPublicKey'];
|
2939 |
-
|
2940 |
-
switch ($keyinfo['algorithm']['algorithm']) {
|
2941 |
-
case 'rsaEncryption':
|
2942 |
-
$publicKey = new RSA();
|
2943 |
-
$publicKey->loadKey($key);
|
2944 |
-
$publicKey->setPublicKey();
|
2945 |
-
break;
|
2946 |
-
default:
|
2947 |
-
return false;
|
2948 |
-
}
|
2949 |
-
|
2950 |
-
return $publicKey;
|
2951 |
-
}
|
2952 |
-
|
2953 |
-
/**
|
2954 |
-
* Load a Certificate Signing Request
|
2955 |
-
*
|
2956 |
-
* @param string $csr
|
2957 |
-
* @access public
|
2958 |
-
* @return mixed
|
2959 |
-
*/
|
2960 |
-
function loadCSR($csr, $mode = self::FORMAT_AUTO_DETECT)
|
2961 |
-
{
|
2962 |
-
if (is_array($csr) && isset($csr['certificationRequestInfo'])) {
|
2963 |
-
unset($this->currentCert);
|
2964 |
-
unset($this->currentKeyIdentifier);
|
2965 |
-
unset($this->signatureSubject);
|
2966 |
-
$this->dn = $csr['certificationRequestInfo']['subject'];
|
2967 |
-
if (!isset($this->dn)) {
|
2968 |
-
return false;
|
2969 |
-
}
|
2970 |
-
|
2971 |
-
$this->currentCert = $csr;
|
2972 |
-
return $csr;
|
2973 |
-
}
|
2974 |
-
|
2975 |
-
// see http://tools.ietf.org/html/rfc2986
|
2976 |
-
|
2977 |
-
$asn1 = new ASN1();
|
2978 |
-
|
2979 |
-
if ($mode != self::FORMAT_DER) {
|
2980 |
-
$newcsr = $this->_extractBER($csr);
|
2981 |
-
if ($mode == self::FORMAT_PEM && $csr == $newcsr) {
|
2982 |
-
return false;
|
2983 |
-
}
|
2984 |
-
$csr = $newcsr;
|
2985 |
-
}
|
2986 |
-
$orig = $csr;
|
2987 |
-
|
2988 |
-
if ($csr === false) {
|
2989 |
-
$this->currentCert = false;
|
2990 |
-
return false;
|
2991 |
-
}
|
2992 |
-
|
2993 |
-
$asn1->loadOIDs($this->oids);
|
2994 |
-
$decoded = $asn1->decodeBER($csr);
|
2995 |
-
|
2996 |
-
if (empty($decoded)) {
|
2997 |
-
$this->currentCert = false;
|
2998 |
-
return false;
|
2999 |
-
}
|
3000 |
-
|
3001 |
-
$csr = $asn1->asn1map($decoded[0], $this->CertificationRequest);
|
3002 |
-
if (!isset($csr) || $csr === false) {
|
3003 |
-
$this->currentCert = false;
|
3004 |
-
return false;
|
3005 |
-
}
|
3006 |
-
|
3007 |
-
$this->_mapInAttributes($csr, 'certificationRequestInfo/attributes', $asn1);
|
3008 |
-
$this->_mapInDNs($csr, 'certificationRequestInfo/subject/rdnSequence', $asn1);
|
3009 |
-
|
3010 |
-
$this->dn = $csr['certificationRequestInfo']['subject'];
|
3011 |
-
|
3012 |
-
$this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
|
3013 |
-
|
3014 |
-
$algorithm = &$csr['certificationRequestInfo']['subjectPKInfo']['algorithm']['algorithm'];
|
3015 |
-
$key = &$csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'];
|
3016 |
-
$key = $this->_reformatKey($algorithm, $key);
|
3017 |
-
|
3018 |
-
switch ($algorithm) {
|
3019 |
-
case 'rsaEncryption':
|
3020 |
-
$this->publicKey = new RSA();
|
3021 |
-
$this->publicKey->loadKey($key);
|
3022 |
-
$this->publicKey->setPublicKey();
|
3023 |
-
break;
|
3024 |
-
default:
|
3025 |
-
$this->publicKey = null;
|
3026 |
-
}
|
3027 |
-
|
3028 |
-
$this->currentKeyIdentifier = null;
|
3029 |
-
$this->currentCert = $csr;
|
3030 |
-
|
3031 |
-
return $csr;
|
3032 |
-
}
|
3033 |
-
|
3034 |
-
/**
|
3035 |
-
* Save CSR request
|
3036 |
-
*
|
3037 |
-
* @param array $csr
|
3038 |
-
* @param int $format optional
|
3039 |
-
* @access public
|
3040 |
-
* @return string
|
3041 |
-
*/
|
3042 |
-
function saveCSR($csr, $format = self::FORMAT_PEM)
|
3043 |
-
{
|
3044 |
-
if (!is_array($csr) || !isset($csr['certificationRequestInfo'])) {
|
3045 |
-
return false;
|
3046 |
-
}
|
3047 |
-
|
3048 |
-
switch (true) {
|
3049 |
-
case !($algorithm = $this->_subArray($csr, 'certificationRequestInfo/subjectPKInfo/algorithm/algorithm')):
|
3050 |
-
case is_object($csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']):
|
3051 |
-
break;
|
3052 |
-
default:
|
3053 |
-
switch ($algorithm) {
|
3054 |
-
case 'rsaEncryption':
|
3055 |
-
$csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']
|
3056 |
-
= base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'])));
|
3057 |
-
$csr['certificationRequestInfo']['subjectPKInfo']['algorithm']['parameters'] = null;
|
3058 |
-
$csr['signatureAlgorithm']['parameters'] = null;
|
3059 |
-
$csr['certificationRequestInfo']['signature']['parameters'] = null;
|
3060 |
-
}
|
3061 |
-
}
|
3062 |
-
|
3063 |
-
$asn1 = new ASN1();
|
3064 |
-
|
3065 |
-
$asn1->loadOIDs($this->oids);
|
3066 |
-
|
3067 |
-
$filters = array();
|
3068 |
-
$filters['certificationRequestInfo']['subject']['rdnSequence']['value']
|
3069 |
-
= array('type' => ASN1::TYPE_UTF8_STRING);
|
3070 |
-
|
3071 |
-
$asn1->loadFilters($filters);
|
3072 |
-
|
3073 |
-
$this->_mapOutDNs($csr, 'certificationRequestInfo/subject/rdnSequence', $asn1);
|
3074 |
-
$this->_mapOutAttributes($csr, 'certificationRequestInfo/attributes', $asn1);
|
3075 |
-
$csr = $asn1->encodeDER($csr, $this->CertificationRequest);
|
3076 |
-
|
3077 |
-
switch ($format) {
|
3078 |
-
case self::FORMAT_DER:
|
3079 |
-
return $csr;
|
3080 |
-
// case self::FORMAT_PEM:
|
3081 |
-
default:
|
3082 |
-
return "-----BEGIN CERTIFICATE REQUEST-----\r\n" . chunk_split(base64_encode($csr), 64) . '-----END CERTIFICATE REQUEST-----';
|
3083 |
-
}
|
3084 |
-
}
|
3085 |
-
|
3086 |
-
/**
|
3087 |
-
* Load a SPKAC CSR
|
3088 |
-
*
|
3089 |
-
* SPKAC's are produced by the HTML5 keygen element:
|
3090 |
-
*
|
3091 |
-
* https://developer.mozilla.org/en-US/docs/HTML/Element/keygen
|
3092 |
-
*
|
3093 |
-
* @param string $csr
|
3094 |
-
* @access public
|
3095 |
-
* @return mixed
|
3096 |
-
*/
|
3097 |
-
function loadSPKAC($spkac)
|
3098 |
-
{
|
3099 |
-
if (is_array($spkac) && isset($spkac['publicKeyAndChallenge'])) {
|
3100 |
-
unset($this->currentCert);
|
3101 |
-
unset($this->currentKeyIdentifier);
|
3102 |
-
unset($this->signatureSubject);
|
3103 |
-
$this->currentCert = $spkac;
|
3104 |
-
return $spkac;
|
3105 |
-
}
|
3106 |
-
|
3107 |
-
// see http://www.w3.org/html/wg/drafts/html/master/forms.html#signedpublickeyandchallenge
|
3108 |
-
|
3109 |
-
$asn1 = new ASN1();
|
3110 |
-
|
3111 |
-
// OpenSSL produces SPKAC's that are preceded by the string SPKAC=
|
3112 |
-
$temp = preg_replace('#(?:SPKAC=)|[ \r\n\\\]#', '', $spkac);
|
3113 |
-
$temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false;
|
3114 |
-
if ($temp != false) {
|
3115 |
-
$spkac = $temp;
|
3116 |
-
}
|
3117 |
-
$orig = $spkac;
|
3118 |
-
|
3119 |
-
if ($spkac === false) {
|
3120 |
-
$this->currentCert = false;
|
3121 |
-
return false;
|
3122 |
-
}
|
3123 |
-
|
3124 |
-
$asn1->loadOIDs($this->oids);
|
3125 |
-
$decoded = $asn1->decodeBER($spkac);
|
3126 |
-
|
3127 |
-
if (empty($decoded)) {
|
3128 |
-
$this->currentCert = false;
|
3129 |
-
return false;
|
3130 |
-
}
|
3131 |
-
|
3132 |
-
$spkac = $asn1->asn1map($decoded[0], $this->SignedPublicKeyAndChallenge);
|
3133 |
-
|
3134 |
-
if (!isset($spkac) || $spkac === false) {
|
3135 |
-
$this->currentCert = false;
|
3136 |
-
return false;
|
3137 |
-
}
|
3138 |
-
|
3139 |
-
$this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
|
3140 |
-
|
3141 |
-
$algorithm = &$spkac['publicKeyAndChallenge']['spki']['algorithm']['algorithm'];
|
3142 |
-
$key = &$spkac['publicKeyAndChallenge']['spki']['subjectPublicKey'];
|
3143 |
-
$key = $this->_reformatKey($algorithm, $key);
|
3144 |
-
|
3145 |
-
switch ($algorithm) {
|
3146 |
-
case 'rsaEncryption':
|
3147 |
-
$this->publicKey = new RSA();
|
3148 |
-
$this->publicKey->loadKey($key);
|
3149 |
-
$this->publicKey->setPublicKey();
|
3150 |
-
break;
|
3151 |
-
default:
|
3152 |
-
$this->publicKey = null;
|
3153 |
-
}
|
3154 |
-
|
3155 |
-
$this->currentKeyIdentifier = null;
|
3156 |
-
$this->currentCert = $spkac;
|
3157 |
-
|
3158 |
-
return $spkac;
|
3159 |
-
}
|
3160 |
-
|
3161 |
-
/**
|
3162 |
-
* Save a SPKAC CSR request
|
3163 |
-
*
|
3164 |
-
* @param array $csr
|
3165 |
-
* @param int $format optional
|
3166 |
-
* @access public
|
3167 |
-
* @return string
|
3168 |
-
*/
|
3169 |
-
function saveSPKAC($spkac, $format = self::FORMAT_PEM)
|
3170 |
-
{
|
3171 |
-
if (!is_array($spkac) || !isset($spkac['publicKeyAndChallenge'])) {
|
3172 |
-
return false;
|
3173 |
-
}
|
3174 |
-
|
3175 |
-
$algorithm = $this->_subArray($spkac, 'publicKeyAndChallenge/spki/algorithm/algorithm');
|
3176 |
-
switch (true) {
|
3177 |
-
case !$algorithm:
|
3178 |
-
case is_object($spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']):
|
3179 |
-
break;
|
3180 |
-
default:
|
3181 |
-
switch ($algorithm) {
|
3182 |
-
case 'rsaEncryption':
|
3183 |
-
$spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']
|
3184 |
-
= base64_encode("\0" . base64_decode(preg_replace('#-.+-|[\r\n]#', '', $spkac['publicKeyAndChallenge']['spki']['subjectPublicKey'])));
|
3185 |
-
}
|
3186 |
-
}
|
3187 |
-
|
3188 |
-
$asn1 = new ASN1();
|
3189 |
-
|
3190 |
-
$asn1->loadOIDs($this->oids);
|
3191 |
-
$spkac = $asn1->encodeDER($spkac, $this->SignedPublicKeyAndChallenge);
|
3192 |
-
|
3193 |
-
switch ($format) {
|
3194 |
-
case self::FORMAT_DER:
|
3195 |
-
return $spkac;
|
3196 |
-
// case self::FORMAT_PEM:
|
3197 |
-
default:
|
3198 |
-
// OpenSSL's implementation of SPKAC requires the SPKAC be preceded by SPKAC= and since there are pretty much
|
3199 |
-
// no other SPKAC decoders phpseclib will use that same format
|
3200 |
-
return 'SPKAC=' . base64_encode($spkac);
|
3201 |
-
}
|
3202 |
-
}
|
3203 |
-
|
3204 |
-
/**
|
3205 |
-
* Load a Certificate Revocation List
|
3206 |
-
*
|
3207 |
-
* @param string $crl
|
3208 |
-
* @access public
|
3209 |
-
* @return mixed
|
3210 |
-
*/
|
3211 |
-
function loadCRL($crl, $mode = self::FORMAT_AUTO_DETECT)
|
3212 |
-
{
|
3213 |
-
if (is_array($crl) && isset($crl['tbsCertList'])) {
|
3214 |
-
$this->currentCert = $crl;
|
3215 |
-
unset($this->signatureSubject);
|
3216 |
-
return $crl;
|
3217 |
-
}
|
3218 |
-
|
3219 |
-
$asn1 = new ASN1();
|
3220 |
-
|
3221 |
-
if ($mode != self::FORMAT_DER) {
|
3222 |
-
$newcrl = $this->_extractBER($crl);
|
3223 |
-
if ($mode == self::FORMAT_PEM && $crl == $newcrl) {
|
3224 |
-
return false;
|
3225 |
-
}
|
3226 |
-
$crl = $newcrl;
|
3227 |
-
}
|
3228 |
-
$orig = $crl;
|
3229 |
-
|
3230 |
-
if ($crl === false) {
|
3231 |
-
$this->currentCert = false;
|
3232 |
-
return false;
|
3233 |
-
}
|
3234 |
-
|
3235 |
-
$asn1->loadOIDs($this->oids);
|
3236 |
-
$decoded = $asn1->decodeBER($crl);
|
3237 |
-
|
3238 |
-
if (empty($decoded)) {
|
3239 |
-
$this->currentCert = false;
|
3240 |
-
return false;
|
3241 |
-
}
|
3242 |
-
|
3243 |
-
$crl = $asn1->asn1map($decoded[0], $this->CertificateList);
|
3244 |
-
if (!isset($crl) || $crl === false) {
|
3245 |
-
$this->currentCert = false;
|
3246 |
-
return false;
|
3247 |
-
}
|
3248 |
-
|
3249 |
-
$this->signatureSubject = substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
|
3250 |
-
|
3251 |
-
$this->_mapInDNs($crl, 'tbsCertList/issuer/rdnSequence', $asn1);
|
3252 |
-
if ($this->_isSubArrayValid($crl, 'tbsCertList/crlExtensions')) {
|
3253 |
-
$this->_mapInExtensions($crl, 'tbsCertList/crlExtensions', $asn1);
|
3254 |
-
}
|
3255 |
-
if ($this->_isSubArrayValid($crl, 'tbsCertList/revokedCertificates')) {
|
3256 |
-
$rclist_ref = &$this->_subArrayUnchecked($crl, 'tbsCertList/revokedCertificates');
|
3257 |
-
if ($rclist_ref) {
|
3258 |
-
$rclist = $crl['tbsCertList']['revokedCertificates'];
|
3259 |
-
foreach ($rclist as $i => $extension) {
|
3260 |
-
if ($this->_isSubArrayValid($rclist, "$i/crlEntryExtensions", $asn1)) {
|
3261 |
-
$this->_mapInExtensions($rclist_ref, "$i/crlEntryExtensions", $asn1);
|
3262 |
-
}
|
3263 |
-
}
|
3264 |
-
}
|
3265 |
-
}
|
3266 |
-
|
3267 |
-
$this->currentKeyIdentifier = null;
|
3268 |
-
$this->currentCert = $crl;
|
3269 |
-
|
3270 |
-
return $crl;
|
3271 |
-
}
|
3272 |
-
|
3273 |
-
/**
|
3274 |
-
* Save Certificate Revocation List.
|
3275 |
-
*
|
3276 |
-
* @param array $crl
|
3277 |
-
* @param int $format optional
|
3278 |
-
* @access public
|
3279 |
-
* @return string
|
3280 |
-
*/
|
3281 |
-
function saveCRL($crl, $format = self::FORMAT_PEM)
|
3282 |
-
{
|
3283 |
-
if (!is_array($crl) || !isset($crl['tbsCertList'])) {
|
3284 |
-
return false;
|
3285 |
-
}
|
3286 |
-
|
3287 |
-
$asn1 = new ASN1();
|
3288 |
-
|
3289 |
-
$asn1->loadOIDs($this->oids);
|
3290 |
-
|
3291 |
-
$filters = array();
|
3292 |
-
$filters['tbsCertList']['issuer']['rdnSequence']['value']
|
3293 |
-
= array('type' => ASN1::TYPE_UTF8_STRING);
|
3294 |
-
$filters['tbsCertList']['signature']['parameters']
|
3295 |
-
= array('type' => ASN1::TYPE_UTF8_STRING);
|
3296 |
-
$filters['signatureAlgorithm']['parameters']
|
3297 |
-
= array('type' => ASN1::TYPE_UTF8_STRING);
|
3298 |
-
|
3299 |
-
if (empty($crl['tbsCertList']['signature']['parameters'])) {
|
3300 |
-
$filters['tbsCertList']['signature']['parameters']
|
3301 |
-
= array('type' => ASN1::TYPE_NULL);
|
3302 |
-
}
|
3303 |
-
|
3304 |
-
if (empty($crl['signatureAlgorithm']['parameters'])) {
|
3305 |
-
$filters['signatureAlgorithm']['parameters']
|
3306 |
-
= array('type' => ASN1::TYPE_NULL);
|
3307 |
-
}
|
3308 |
-
|
3309 |
-
$asn1->loadFilters($filters);
|
3310 |
-
|
3311 |
-
$this->_mapOutDNs($crl, 'tbsCertList/issuer/rdnSequence', $asn1);
|
3312 |
-
$this->_mapOutExtensions($crl, 'tbsCertList/crlExtensions', $asn1);
|
3313 |
-
$rclist = &$this->_subArray($crl, 'tbsCertList/revokedCertificates');
|
3314 |
-
if (is_array($rclist)) {
|
3315 |
-
foreach ($rclist as $i => $extension) {
|
3316 |
-
$this->_mapOutExtensions($rclist, "$i/crlEntryExtensions", $asn1);
|
3317 |
-
}
|
3318 |
-
}
|
3319 |
-
|
3320 |
-
$crl = $asn1->encodeDER($crl, $this->CertificateList);
|
3321 |
-
|
3322 |
-
switch ($format) {
|
3323 |
-
case self::FORMAT_DER:
|
3324 |
-
return $crl;
|
3325 |
-
// case self::FORMAT_PEM:
|
3326 |
-
default:
|
3327 |
-
return "-----BEGIN X509 CRL-----\r\n" . chunk_split(base64_encode($crl), 64) . '-----END X509 CRL-----';
|
3328 |
-
}
|
3329 |
-
}
|
3330 |
-
|
3331 |
-
/**
|
3332 |
-
* Helper function to build a time field according to RFC 3280 section
|
3333 |
-
* - 4.1.2.5 Validity
|
3334 |
-
* - 5.1.2.4 This Update
|
3335 |
-
* - 5.1.2.5 Next Update
|
3336 |
-
* - 5.1.2.6 Revoked Certificates
|
3337 |
-
* by choosing utcTime iff year of date given is before 2050 and generalTime else.
|
3338 |
-
*
|
3339 |
-
* @param string $date in format date('D, d M Y H:i:s O')
|
3340 |
-
* @access private
|
3341 |
-
* @return array
|
3342 |
-
*/
|
3343 |
-
function _timeField($date)
|
3344 |
-
{
|
3345 |
-
if ($date instanceof Element) {
|
3346 |
-
return $date;
|
3347 |
-
}
|
3348 |
-
$dateObj = new DateTime($date, new DateTimeZone('GMT'));
|
3349 |
-
$year = $dateObj->format('Y'); // the same way ASN1.php parses this
|
3350 |
-
if ($year < 2050) {
|
3351 |
-
return array('utcTime' => $date);
|
3352 |
-
} else {
|
3353 |
-
return array('generalTime' => $date);
|
3354 |
-
}
|
3355 |
-
}
|
3356 |
-
|
3357 |
-
/**
|
3358 |
-
* Sign an X.509 certificate
|
3359 |
-
*
|
3360 |
-
* $issuer's private key needs to be loaded.
|
3361 |
-
* $subject can be either an existing X.509 cert (if you want to resign it),
|
3362 |
-
* a CSR or something with the DN and public key explicitly set.
|
3363 |
-
*
|
3364 |
-
* @param \phpseclib\File\X509 $issuer
|
3365 |
-
* @param \phpseclib\File\X509 $subject
|
3366 |
-
* @param string $signatureAlgorithm optional
|
3367 |
-
* @access public
|
3368 |
-
* @return mixed
|
3369 |
-
*/
|
3370 |
-
function sign($issuer, $subject, $signatureAlgorithm = 'sha1WithRSAEncryption')
|
3371 |
-
{
|
3372 |
-
if (!is_object($issuer->privateKey) || empty($issuer->dn)) {
|
3373 |
-
return false;
|
3374 |
-
}
|
3375 |
-
|
3376 |
-
if (isset($subject->publicKey) && !($subjectPublicKey = $subject->_formatSubjectPublicKey())) {
|
3377 |
-
return false;
|
3378 |
-
}
|
3379 |
-
|
3380 |
-
$currentCert = isset($this->currentCert) ? $this->currentCert : null;
|
3381 |
-
$signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject: null;
|
3382 |
-
|
3383 |
-
if (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertificate'])) {
|
3384 |
-
$this->currentCert = $subject->currentCert;
|
3385 |
-
$this->currentCert['tbsCertificate']['signature']['algorithm'] = $signatureAlgorithm;
|
3386 |
-
$this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm;
|
3387 |
-
|
3388 |
-
if (!empty($this->startDate)) {
|
3389 |
-
$this->currentCert['tbsCertificate']['validity']['notBefore'] = $this->_timeField($this->startDate);
|
3390 |
-
}
|
3391 |
-
if (!empty($this->endDate)) {
|
3392 |
-
$this->currentCert['tbsCertificate']['validity']['notAfter'] = $this->_timeField($this->endDate);
|
3393 |
-
}
|
3394 |
-
if (!empty($this->serialNumber)) {
|
3395 |
-
$this->currentCert['tbsCertificate']['serialNumber'] = $this->serialNumber;
|
3396 |
-
}
|
3397 |
-
if (!empty($subject->dn)) {
|
3398 |
-
$this->currentCert['tbsCertificate']['subject'] = $subject->dn;
|
3399 |
-
}
|
3400 |
-
if (!empty($subject->publicKey)) {
|
3401 |
-
$this->currentCert['tbsCertificate']['subjectPublicKeyInfo'] = $subjectPublicKey;
|
3402 |
-
}
|
3403 |
-
$this->removeExtension('id-ce-authorityKeyIdentifier');
|
3404 |
-
if (isset($subject->domains)) {
|
3405 |
-
$this->removeExtension('id-ce-subjectAltName');
|
3406 |
-
}
|
3407 |
-
} elseif (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertList'])) {
|
3408 |
-
return false;
|
3409 |
-
} else {
|
3410 |
-
if (!isset($subject->publicKey)) {
|
3411 |
-
return false;
|
3412 |
-
}
|
3413 |
-
|
3414 |
-
$startDate = new DateTime('now', new DateTimeZone(@date_default_timezone_get()));
|
3415 |
-
$startDate = !empty($this->startDate) ? $this->startDate : $startDate->format('D, d M Y H:i:s O');
|
3416 |
-
|
3417 |
-
$endDate = new DateTime('+1 year', new DateTimeZone(@date_default_timezone_get()));
|
3418 |
-
$endDate = !empty($this->endDate) ? $this->endDate : $endDate->format('D, d M Y H:i:s O');
|
3419 |
-
|
3420 |
-
/* "The serial number MUST be a positive integer"
|
3421 |
-
"Conforming CAs MUST NOT use serialNumber values longer than 20 octets."
|
3422 |
-
-- https://tools.ietf.org/html/rfc5280#section-4.1.2.2
|
3423 |
-
|
3424 |
-
for the integer to be positive the leading bit needs to be 0 hence the
|
3425 |
-
application of a bitmap
|
3426 |
-
*/
|
3427 |
-
$serialNumber = !empty($this->serialNumber) ?
|
3428 |
-
$this->serialNumber :
|
3429 |
-
new BigInteger(Random::string(20) & ("\x7F" . str_repeat("\xFF", 19)), 256);
|
3430 |
-
|
3431 |
-
$this->currentCert = array(
|
3432 |
-
'tbsCertificate' =>
|
3433 |
-
array(
|
3434 |
-
'version' => 'v3',
|
3435 |
-
'serialNumber' => $serialNumber, // $this->setserialNumber()
|
3436 |
-
'signature' => array('algorithm' => $signatureAlgorithm),
|
3437 |
-
'issuer' => false, // this is going to be overwritten later
|
3438 |
-
'validity' => array(
|
3439 |
-
'notBefore' => $this->_timeField($startDate), // $this->setStartDate()
|
3440 |
-
'notAfter' => $this->_timeField($endDate) // $this->setEndDate()
|
3441 |
-
),
|
3442 |
-
'subject' => $subject->dn,
|
3443 |
-
'subjectPublicKeyInfo' => $subjectPublicKey
|
3444 |
-
),
|
3445 |
-
'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
|
3446 |
-
'signature' => false // this is going to be overwritten later
|
3447 |
-
);
|
3448 |
-
|
3449 |
-
// Copy extensions from CSR.
|
3450 |
-
$csrexts = $subject->getAttribute('pkcs-9-at-extensionRequest', 0);
|
3451 |
-
|
3452 |
-
if (!empty($csrexts)) {
|
3453 |
-
$this->currentCert['tbsCertificate']['extensions'] = $csrexts;
|
3454 |
-
}
|
3455 |
-
}
|
3456 |
-
|
3457 |
-
$this->currentCert['tbsCertificate']['issuer'] = $issuer->dn;
|
3458 |
-
|
3459 |
-
if (isset($issuer->currentKeyIdentifier)) {
|
3460 |
-
$this->setExtension('id-ce-authorityKeyIdentifier', array(
|
3461 |
-
//'authorityCertIssuer' => array(
|
3462 |
-
// array(
|
3463 |
-
// 'directoryName' => $issuer->dn
|
3464 |
-
// )
|
3465 |
-
//),
|
3466 |
-
'keyIdentifier' => $issuer->currentKeyIdentifier
|
3467 |
-
));
|
3468 |
-
//$extensions = &$this->currentCert['tbsCertificate']['extensions'];
|
3469 |
-
//if (isset($issuer->serialNumber)) {
|
3470 |
-
// $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber;
|
3471 |
-
//}
|
3472 |
-
//unset($extensions);
|
3473 |
-
}
|
3474 |
-
|
3475 |
-
if (isset($subject->currentKeyIdentifier)) {
|
3476 |
-
$this->setExtension('id-ce-subjectKeyIdentifier', $subject->currentKeyIdentifier);
|
3477 |
-
}
|
3478 |
-
|
3479 |
-
$altName = array();
|
3480 |
-
|
3481 |
-
if (isset($subject->domains) && count($subject->domains)) {
|
3482 |
-
$altName = array_map(array('\phpseclib\File\X509', '_dnsName'), $subject->domains);
|
3483 |
-
}
|
3484 |
-
|
3485 |
-
if (isset($subject->ipAddresses) && count($subject->ipAddresses)) {
|
3486 |
-
// should an IP address appear as the CN if no domain name is specified? idk
|
3487 |
-
//$ips = count($subject->domains) ? $subject->ipAddresses : array_slice($subject->ipAddresses, 1);
|
3488 |
-
$ipAddresses = array();
|
3489 |
-
foreach ($subject->ipAddresses as $ipAddress) {
|
3490 |
-
$encoded = $subject->_ipAddress($ipAddress);
|
3491 |
-
if ($encoded !== false) {
|
3492 |
-
$ipAddresses[] = $encoded;
|
3493 |
-
}
|
3494 |
-
}
|
3495 |
-
if (count($ipAddresses)) {
|
3496 |
-
$altName = array_merge($altName, $ipAddresses);
|
3497 |
-
}
|
3498 |
-
}
|
3499 |
-
|
3500 |
-
if (!empty($altName)) {
|
3501 |
-
$this->setExtension('id-ce-subjectAltName', $altName);
|
3502 |
-
}
|
3503 |
-
|
3504 |
-
if ($this->caFlag) {
|
3505 |
-
$keyUsage = $this->getExtension('id-ce-keyUsage');
|
3506 |
-
if (!$keyUsage) {
|
3507 |
-
$keyUsage = array();
|
3508 |
-
}
|
3509 |
-
|
3510 |
-
$this->setExtension(
|
3511 |
-
'id-ce-keyUsage',
|
3512 |
-
array_values(array_unique(array_merge($keyUsage, array('cRLSign', 'keyCertSign'))))
|
3513 |
-
);
|
3514 |
-
|
3515 |
-
$basicConstraints = $this->getExtension('id-ce-basicConstraints');
|
3516 |
-
if (!$basicConstraints) {
|
3517 |
-
$basicConstraints = array();
|
3518 |
-
}
|
3519 |
-
|
3520 |
-
$this->setExtension(
|
3521 |
-
'id-ce-basicConstraints',
|
3522 |
-
array_unique(array_merge(array('cA' => true), $basicConstraints)),
|
3523 |
-
true
|
3524 |
-
);
|
3525 |
-
|
3526 |
-
if (!isset($subject->currentKeyIdentifier)) {
|
3527 |
-
$this->setExtension('id-ce-subjectKeyIdentifier', base64_encode($this->computeKeyIdentifier($this->currentCert)), false, false);
|
3528 |
-
}
|
3529 |
-
}
|
3530 |
-
|
3531 |
-
// resync $this->signatureSubject
|
3532 |
-
// save $tbsCertificate in case there are any \phpseclib\File\ASN1\Element objects in it
|
3533 |
-
$tbsCertificate = $this->currentCert['tbsCertificate'];
|
3534 |
-
$this->loadX509($this->saveX509($this->currentCert));
|
3535 |
-
|
3536 |
-
$result = $this->_sign($issuer->privateKey, $signatureAlgorithm);
|
3537 |
-
$result['tbsCertificate'] = $tbsCertificate;
|
3538 |
-
|
3539 |
-
$this->currentCert = $currentCert;
|
3540 |
-
$this->signatureSubject = $signatureSubject;
|
3541 |
-
|
3542 |
-
return $result;
|
3543 |
-
}
|
3544 |
-
|
3545 |
-
/**
|
3546 |
-
* Sign a CSR
|
3547 |
-
*
|
3548 |
-
* @access public
|
3549 |
-
* @return mixed
|
3550 |
-
*/
|
3551 |
-
function signCSR($signatureAlgorithm = 'sha1WithRSAEncryption')
|
3552 |
-
{
|
3553 |
-
if (!is_object($this->privateKey) || empty($this->dn)) {
|
3554 |
-
return false;
|
3555 |
-
}
|
3556 |
-
|
3557 |
-
$origPublicKey = $this->publicKey;
|
3558 |
-
$class = get_class($this->privateKey);
|
3559 |
-
$this->publicKey = new $class();
|
3560 |
-
$this->publicKey->loadKey($this->privateKey->getPublicKey());
|
3561 |
-
$this->publicKey->setPublicKey();
|
3562 |
-
if (!($publicKey = $this->_formatSubjectPublicKey())) {
|
3563 |
-
return false;
|
3564 |
-
}
|
3565 |
-
$this->publicKey = $origPublicKey;
|
3566 |
-
|
3567 |
-
$currentCert = isset($this->currentCert) ? $this->currentCert : null;
|
3568 |
-
$signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject: null;
|
3569 |
-
|
3570 |
-
if (isset($this->currentCert) && is_array($this->currentCert) && isset($this->currentCert['certificationRequestInfo'])) {
|
3571 |
-
$this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm;
|
3572 |
-
if (!empty($this->dn)) {
|
3573 |
-
$this->currentCert['certificationRequestInfo']['subject'] = $this->dn;
|
3574 |
-
}
|
3575 |
-
$this->currentCert['certificationRequestInfo']['subjectPKInfo'] = $publicKey;
|
3576 |
-
} else {
|
3577 |
-
$this->currentCert = array(
|
3578 |
-
'certificationRequestInfo' =>
|
3579 |
-
array(
|
3580 |
-
'version' => 'v1',
|
3581 |
-
'subject' => $this->dn,
|
3582 |
-
'subjectPKInfo' => $publicKey
|
3583 |
-
),
|
3584 |
-
'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
|
3585 |
-
'signature' => false // this is going to be overwritten later
|
3586 |
-
);
|
3587 |
-
}
|
3588 |
-
|
3589 |
-
// resync $this->signatureSubject
|
3590 |
-
// save $certificationRequestInfo in case there are any \phpseclib\File\ASN1\Element objects in it
|
3591 |
-
$certificationRequestInfo = $this->currentCert['certificationRequestInfo'];
|
3592 |
-
$this->loadCSR($this->saveCSR($this->currentCert));
|
3593 |
-
|
3594 |
-
$result = $this->_sign($this->privateKey, $signatureAlgorithm);
|
3595 |
-
$result['certificationRequestInfo'] = $certificationRequestInfo;
|
3596 |
-
|
3597 |
-
$this->currentCert = $currentCert;
|
3598 |
-
$this->signatureSubject = $signatureSubject;
|
3599 |
-
|
3600 |
-
return $result;
|
3601 |
-
}
|
3602 |
-
|
3603 |
-
/**
|
3604 |
-
* Sign a SPKAC
|
3605 |
-
*
|
3606 |
-
* @access public
|
3607 |
-
* @return mixed
|
3608 |
-
*/
|
3609 |
-
function signSPKAC($signatureAlgorithm = 'sha1WithRSAEncryption')
|
3610 |
-
{
|
3611 |
-
if (!is_object($this->privateKey)) {
|
3612 |
-
return false;
|
3613 |
-
}
|
3614 |
-
|
3615 |
-
$origPublicKey = $this->publicKey;
|
3616 |
-
$class = get_class($this->privateKey);
|
3617 |
-
$this->publicKey = new $class();
|
3618 |
-
$this->publicKey->loadKey($this->privateKey->getPublicKey());
|
3619 |
-
$this->publicKey->setPublicKey();
|
3620 |
-
$publicKey = $this->_formatSubjectPublicKey();
|
3621 |
-
if (!$publicKey) {
|
3622 |
-
return false;
|
3623 |
-
}
|
3624 |
-
$this->publicKey = $origPublicKey;
|
3625 |
-
|
3626 |
-
$currentCert = isset($this->currentCert) ? $this->currentCert : null;
|
3627 |
-
$signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject: null;
|
3628 |
-
|
3629 |
-
// re-signing a SPKAC seems silly but since everything else supports re-signing why not?
|
3630 |
-
if (isset($this->currentCert) && is_array($this->currentCert) && isset($this->currentCert['publicKeyAndChallenge'])) {
|
3631 |
-
$this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm;
|
3632 |
-
$this->currentCert['publicKeyAndChallenge']['spki'] = $publicKey;
|
3633 |
-
if (!empty($this->challenge)) {
|
3634 |
-
// the bitwise AND ensures that the output is a valid IA5String
|
3635 |
-
$this->currentCert['publicKeyAndChallenge']['challenge'] = $this->challenge & str_repeat("\x7F", strlen($this->challenge));
|
3636 |
-
}
|
3637 |
-
} else {
|
3638 |
-
$this->currentCert = array(
|
3639 |
-
'publicKeyAndChallenge' =>
|
3640 |
-
array(
|
3641 |
-
'spki' => $publicKey,
|
3642 |
-
// quoting <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/keygen>,
|
3643 |
-
// "A challenge string that is submitted along with the public key. Defaults to an empty string if not specified."
|
3644 |
-
// both Firefox and OpenSSL ("openssl spkac -key private.key") behave this way
|
3645 |
-
// we could alternatively do this instead if we ignored the specs:
|
3646 |
-
// Random::string(8) & str_repeat("\x7F", 8)
|
3647 |
-
'challenge' => !empty($this->challenge) ? $this->challenge : ''
|
3648 |
-
),
|
3649 |
-
'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
|
3650 |
-
'signature' => false // this is going to be overwritten later
|
3651 |
-
);
|
3652 |
-
}
|
3653 |
-
|
3654 |
-
// resync $this->signatureSubject
|
3655 |
-
// save $publicKeyAndChallenge in case there are any \phpseclib\File\ASN1\Element objects in it
|
3656 |
-
$publicKeyAndChallenge = $this->currentCert['publicKeyAndChallenge'];
|
3657 |
-
$this->loadSPKAC($this->saveSPKAC($this->currentCert));
|
3658 |
-
|
3659 |
-
$result = $this->_sign($this->privateKey, $signatureAlgorithm);
|
3660 |
-
$result['publicKeyAndChallenge'] = $publicKeyAndChallenge;
|
3661 |
-
|
3662 |
-
$this->currentCert = $currentCert;
|
3663 |
-
$this->signatureSubject = $signatureSubject;
|
3664 |
-
|
3665 |
-
return $result;
|
3666 |
-
}
|
3667 |
-
|
3668 |
-
/**
|
3669 |
-
* Sign a CRL
|
3670 |
-
*
|
3671 |
-
* $issuer's private key needs to be loaded.
|
3672 |
-
*
|
3673 |
-
* @param \phpseclib\File\X509 $issuer
|
3674 |
-
* @param \phpseclib\File\X509 $crl
|
3675 |
-
* @param string $signatureAlgorithm optional
|
3676 |
-
* @access public
|
3677 |
-
* @return mixed
|
3678 |
-
*/
|
3679 |
-
function signCRL($issuer, $crl, $signatureAlgorithm = 'sha1WithRSAEncryption')
|
3680 |
-
{
|
3681 |
-
if (!is_object($issuer->privateKey) || empty($issuer->dn)) {
|
3682 |
-
return false;
|
3683 |
-
}
|
3684 |
-
|
3685 |
-
$currentCert = isset($this->currentCert) ? $this->currentCert : null;
|
3686 |
-
$signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null;
|
3687 |
-
|
3688 |
-
$thisUpdate = new DateTime('now', new DateTimeZone(@date_default_timezone_get()));
|
3689 |
-
$thisUpdate = !empty($this->startDate) ? $this->startDate : $thisUpdate->format('D, d M Y H:i:s O');
|
3690 |
-
|
3691 |
-
if (isset($crl->currentCert) && is_array($crl->currentCert) && isset($crl->currentCert['tbsCertList'])) {
|
3692 |
-
$this->currentCert = $crl->currentCert;
|
3693 |
-
$this->currentCert['tbsCertList']['signature']['algorithm'] = $signatureAlgorithm;
|
3694 |
-
$this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm;
|
3695 |
-
} else {
|
3696 |
-
$this->currentCert = array(
|
3697 |
-
'tbsCertList' =>
|
3698 |
-
array(
|
3699 |
-
'version' => 'v2',
|
3700 |
-
'signature' => array('algorithm' => $signatureAlgorithm),
|
3701 |
-
'issuer' => false, // this is going to be overwritten later
|
3702 |
-
'thisUpdate' => $this->_timeField($thisUpdate) // $this->setStartDate()
|
3703 |
-
),
|
3704 |
-
'signatureAlgorithm' => array('algorithm' => $signatureAlgorithm),
|
3705 |
-
'signature' => false // this is going to be overwritten later
|
3706 |
-
);
|
3707 |
-
}
|
3708 |
-
|
3709 |
-
$tbsCertList = &$this->currentCert['tbsCertList'];
|
3710 |
-
$tbsCertList['issuer'] = $issuer->dn;
|
3711 |
-
$tbsCertList['thisUpdate'] = $this->_timeField($thisUpdate);
|
3712 |
-
|
3713 |
-
if (!empty($this->endDate)) {
|
3714 |
-
$tbsCertList['nextUpdate'] = $this->_timeField($this->endDate); // $this->setEndDate()
|
3715 |
-
} else {
|
3716 |
-
unset($tbsCertList['nextUpdate']);
|
3717 |
-
}
|
3718 |
-
|
3719 |
-
if (!empty($this->serialNumber)) {
|
3720 |
-
$crlNumber = $this->serialNumber;
|
3721 |
-
} else {
|
3722 |
-
$crlNumber = $this->getExtension('id-ce-cRLNumber');
|
3723 |
-
// "The CRL number is a non-critical CRL extension that conveys a
|
3724 |
-
// monotonically increasing sequence number for a given CRL scope and
|
3725 |
-
// CRL issuer. This extension allows users to easily determine when a
|
3726 |
-
// particular CRL supersedes another CRL."
|
3727 |
-
// -- https://tools.ietf.org/html/rfc5280#section-5.2.3
|
3728 |
-
$crlNumber = $crlNumber !== false ? $crlNumber->add(new BigInteger(1)) : null;
|
3729 |
-
}
|
3730 |
-
|
3731 |
-
$this->removeExtension('id-ce-authorityKeyIdentifier');
|
3732 |
-
$this->removeExtension('id-ce-issuerAltName');
|
3733 |
-
|
3734 |
-
// Be sure version >= v2 if some extension found.
|
3735 |
-
$version = isset($tbsCertList['version']) ? $tbsCertList['version'] : 0;
|
3736 |
-
if (!$version) {
|
3737 |
-
if (!empty($tbsCertList['crlExtensions'])) {
|
3738 |
-
$version = 1; // v2.
|
3739 |
-
} elseif (!empty($tbsCertList['revokedCertificates'])) {
|
3740 |
-
foreach ($tbsCertList['revokedCertificates'] as $cert) {
|
3741 |
-
if (!empty($cert['crlEntryExtensions'])) {
|
3742 |
-
$version = 1; // v2.
|
3743 |
-
}
|
3744 |
-
}
|
3745 |
-
}
|
3746 |
-
|
3747 |
-
if ($version) {
|
3748 |
-
$tbsCertList['version'] = $version;
|
3749 |
-
}
|
3750 |
-
}
|
3751 |
-
|
3752 |
-
// Store additional extensions.
|
3753 |
-
if (!empty($tbsCertList['version'])) { // At least v2.
|
3754 |
-
if (!empty($crlNumber)) {
|
3755 |
-
$this->setExtension('id-ce-cRLNumber', $crlNumber);
|
3756 |
-
}
|
3757 |
-
|
3758 |
-
if (isset($issuer->currentKeyIdentifier)) {
|
3759 |
-
$this->setExtension('id-ce-authorityKeyIdentifier', array(
|
3760 |
-
//'authorityCertIssuer' => array(
|
3761 |
-
// array(
|
3762 |
-
// 'directoryName' => $issuer->dn
|
3763 |
-
// )
|
3764 |
-
//),
|
3765 |
-
'keyIdentifier' => $issuer->currentKeyIdentifier
|
3766 |
-
));
|
3767 |
-
//$extensions = &$tbsCertList['crlExtensions'];
|
3768 |
-
//if (isset($issuer->serialNumber)) {
|
3769 |
-
// $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber;
|
3770 |
-
//}
|
3771 |
-
//unset($extensions);
|
3772 |
-
}
|
3773 |
-
|
3774 |
-
$issuerAltName = $this->getExtension('id-ce-subjectAltName', $issuer->currentCert);
|
3775 |
-
|
3776 |
-
if ($issuerAltName !== false) {
|
3777 |
-
$this->setExtension('id-ce-issuerAltName', $issuerAltName);
|
3778 |
-
}
|
3779 |
-
}
|
3780 |
-
|
3781 |
-
if (empty($tbsCertList['revokedCertificates'])) {
|
3782 |
-
unset($tbsCertList['revokedCertificates']);
|
3783 |
-
}
|
3784 |
-
|
3785 |
-
unset($tbsCertList);
|
3786 |
-
|
3787 |
-
// resync $this->signatureSubject
|
3788 |
-
// save $tbsCertList in case there are any \phpseclib\File\ASN1\Element objects in it
|
3789 |
-
$tbsCertList = $this->currentCert['tbsCertList'];
|
3790 |
-
$this->loadCRL($this->saveCRL($this->currentCert));
|
3791 |
-
|
3792 |
-
$result = $this->_sign($issuer->privateKey, $signatureAlgorithm);
|
3793 |
-
$result['tbsCertList'] = $tbsCertList;
|
3794 |
-
|
3795 |
-
$this->currentCert = $currentCert;
|
3796 |
-
$this->signatureSubject = $signatureSubject;
|
3797 |
-
|
3798 |
-
return $result;
|
3799 |
-
}
|
3800 |
-
|
3801 |
-
/**
|
3802 |
-
* X.509 certificate signing helper function.
|
3803 |
-
*
|
3804 |
-
* @param object $key
|
3805 |
-
* @param \phpseclib\File\X509 $subject
|
3806 |
-
* @param string $signatureAlgorithm
|
3807 |
-
* @access public
|
3808 |
-
* @return mixed
|
3809 |
-
*/
|
3810 |
-
function _sign($key, $signatureAlgorithm)
|
3811 |
-
{
|
3812 |
-
if ($key instanceof RSA) {
|
3813 |
-
switch ($signatureAlgorithm) {
|
3814 |
-
case 'md2WithRSAEncryption':
|
3815 |
-
case 'md5WithRSAEncryption':
|
3816 |
-
case 'sha1WithRSAEncryption':
|
3817 |
-
case 'sha224WithRSAEncryption':
|
3818 |
-
case 'sha256WithRSAEncryption':
|
3819 |
-
case 'sha384WithRSAEncryption':
|
3820 |
-
case 'sha512WithRSAEncryption':
|
3821 |
-
$key->setHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm));
|
3822 |
-
$key->setSignatureMode(RSA::SIGNATURE_PKCS1);
|
3823 |
-
|
3824 |
-
$this->currentCert['signature'] = base64_encode("\0" . $key->sign($this->signatureSubject));
|
3825 |
-
return $this->currentCert;
|
3826 |
-
}
|
3827 |
-
}
|
3828 |
-
|
3829 |
-
return false;
|
3830 |
-
}
|
3831 |
-
|
3832 |
-
/**
|
3833 |
-
* Set certificate start date
|
3834 |
-
*
|
3835 |
-
* @param string $date
|
3836 |
-
* @access public
|
3837 |
-
*/
|
3838 |
-
function setStartDate($date)
|
3839 |
-
{
|
3840 |
-
if (!is_object($date) || !is_a($date, 'DateTime')) {
|
3841 |
-
$date = new DateTime($date, new DateTimeZone(@date_default_timezone_get()));
|
3842 |
-
}
|
3843 |
-
|
3844 |
-
$this->startDate = $date->format('D, d M Y H:i:s O');
|
3845 |
-
}
|
3846 |
-
|
3847 |
-
/**
|
3848 |
-
* Set certificate end date
|
3849 |
-
*
|
3850 |
-
* @param string $date
|
3851 |
-
* @access public
|
3852 |
-
*/
|
3853 |
-
function setEndDate($date)
|
3854 |
-
{
|
3855 |
-
/*
|
3856 |
-
To indicate that a certificate has no well-defined expiration date,
|
3857 |
-
the notAfter SHOULD be assigned the GeneralizedTime value of
|
3858 |
-
99991231235959Z.
|
3859 |
-
|
3860 |
-
-- http://tools.ietf.org/html/rfc5280#section-4.1.2.5
|
3861 |
-
*/
|
3862 |
-
if (strtolower($date) == 'lifetime') {
|
3863 |
-
$temp = '99991231235959Z';
|
3864 |
-
$asn1 = new ASN1();
|
3865 |
-
$temp = chr(ASN1::TYPE_GENERALIZED_TIME) . $asn1->_encodeLength(strlen($temp)) . $temp;
|
3866 |
-
$this->endDate = new Element($temp);
|
3867 |
-
} else {
|
3868 |
-
if (!is_object($date) || !is_a($date, 'DateTime')) {
|
3869 |
-
$date = new DateTime($date, new DateTimeZone(@date_default_timezone_get()));
|
3870 |
-
}
|
3871 |
-
|
3872 |
-
$this->endDate = $date->format('D, d M Y H:i:s O');
|
3873 |
-
}
|
3874 |
-
}
|
3875 |
-
|
3876 |
-
/**
|
3877 |
-
* Set Serial Number
|
3878 |
-
*
|
3879 |
-
* @param string $serial
|
3880 |
-
* @param $base optional
|
3881 |
-
* @access public
|
3882 |
-
*/
|
3883 |
-
function setSerialNumber($serial, $base = -256)
|
3884 |
-
{
|
3885 |
-
$this->serialNumber = new BigInteger($serial, $base);
|
3886 |
-
}
|
3887 |
-
|
3888 |
-
/**
|
3889 |
-
* Turns the certificate into a certificate authority
|
3890 |
-
*
|
3891 |
-
* @access public
|
3892 |
-
*/
|
3893 |
-
function makeCA()
|
3894 |
-
{
|
3895 |
-
$this->caFlag = true;
|
3896 |
-
}
|
3897 |
-
|
3898 |
-
/**
|
3899 |
-
* Check for validity of subarray
|
3900 |
-
*
|
3901 |
-
* This is intended for use in conjunction with _subArrayUnchecked(),
|
3902 |
-
* implementing the checks included in _subArray() but without copying
|
3903 |
-
* a potentially large array by passing its reference by-value to is_array().
|
3904 |
-
*
|
3905 |
-
* @param array $root
|
3906 |
-
* @param string $path
|
3907 |
-
* @return boolean
|
3908 |
-
* @access private
|
3909 |
-
*/
|
3910 |
-
function _isSubArrayValid($root, $path)
|
3911 |
-
{
|
3912 |
-
if (!is_array($root)) {
|
3913 |
-
return false;
|
3914 |
-
}
|
3915 |
-
|
3916 |
-
foreach (explode('/', $path) as $i) {
|
3917 |
-
if (!is_array($root)) {
|
3918 |
-
return false;
|
3919 |
-
}
|
3920 |
-
|
3921 |
-
if (!isset($root[$i])) {
|
3922 |
-
return true;
|
3923 |
-
}
|
3924 |
-
|
3925 |
-
$root = $root[$i];
|
3926 |
-
}
|
3927 |
-
|
3928 |
-
return true;
|
3929 |
-
}
|
3930 |
-
|
3931 |
-
/**
|
3932 |
-
* Get a reference to a subarray
|
3933 |
-
*
|
3934 |
-
* This variant of _subArray() does no is_array() checking,
|
3935 |
-
* so $root should be checked with _isSubArrayValid() first.
|
3936 |
-
*
|
3937 |
-
* This is here for performance reasons:
|
3938 |
-
* Passing a reference (i.e. $root) by-value (i.e. to is_array())
|
3939 |
-
* creates a copy. If $root is an especially large array, this is expensive.
|
3940 |
-
*
|
3941 |
-
* @param array $root
|
3942 |
-
* @param string $path absolute path with / as component separator
|
3943 |
-
* @param bool $create optional
|
3944 |
-
* @access private
|
3945 |
-
* @return array|false
|
3946 |
-
*/
|
3947 |
-
function &_subArrayUnchecked(&$root, $path, $create = false)
|
3948 |
-
{
|
3949 |
-
$false = false;
|
3950 |
-
|
3951 |
-
foreach (explode('/', $path) as $i) {
|
3952 |
-
if (!isset($root[$i])) {
|
3953 |
-
if (!$create) {
|
3954 |
-
return $false;
|
3955 |
-
}
|
3956 |
-
|
3957 |
-
$root[$i] = array();
|
3958 |
-
}
|
3959 |
-
|
3960 |
-
$root = &$root[$i];
|
3961 |
-
}
|
3962 |
-
|
3963 |
-
return $root;
|
3964 |
-
}
|
3965 |
-
|
3966 |
-
/**
|
3967 |
-
* Get a reference to a subarray
|
3968 |
-
*
|
3969 |
-
* @param array $root
|
3970 |
-
* @param string $path absolute path with / as component separator
|
3971 |
-
* @param bool $create optional
|
3972 |
-
* @access private
|
3973 |
-
* @return array|false
|
3974 |
-
*/
|
3975 |
-
function &_subArray(&$root, $path, $create = false)
|
3976 |
-
{
|
3977 |
-
$false = false;
|
3978 |
-
|
3979 |
-
if (!is_array($root)) {
|
3980 |
-
return $false;
|
3981 |
-
}
|
3982 |
-
|
3983 |
-
foreach (explode('/', $path) as $i) {
|
3984 |
-
if (!is_array($root)) {
|
3985 |
-
return $false;
|
3986 |
-
}
|
3987 |
-
|
3988 |
-
if (!isset($root[$i])) {
|
3989 |
-
if (!$create) {
|
3990 |
-
return $false;
|
3991 |
-
}
|
3992 |
-
|
3993 |
-
$root[$i] = array();
|
3994 |
-
}
|
3995 |
-
|
3996 |
-
$root = &$root[$i];
|
3997 |
-
}
|
3998 |
-
|
3999 |
-
return $root;
|
4000 |
-
}
|
4001 |
-
|
4002 |
-
/**
|
4003 |
-
* Get a reference to an extension subarray
|
4004 |
-
*
|
4005 |
-
* @param array $root
|
4006 |
-
* @param string $path optional absolute path with / as component separator
|
4007 |
-
* @param bool $create optional
|
4008 |
-
* @access private
|
4009 |
-
* @return array|false
|
4010 |
-
*/
|
4011 |
-
function &_extensions(&$root, $path = null, $create = false)
|
4012 |
-
{
|
4013 |
-
if (!isset($root)) {
|
4014 |
-
$root = $this->currentCert;
|
4015 |
-
}
|
4016 |
-
|
4017 |
-
switch (true) {
|
4018 |
-
case !empty($path):
|
4019 |
-
case !is_array($root):
|
4020 |
-
break;
|
4021 |
-
case isset($root['tbsCertificate']):
|
4022 |
-
$path = 'tbsCertificate/extensions';
|
4023 |
-
break;
|
4024 |
-
case isset($root['tbsCertList']):
|
4025 |
-
$path = 'tbsCertList/crlExtensions';
|
4026 |
-
break;
|
4027 |
-
case isset($root['certificationRequestInfo']):
|
4028 |
-
$pth = 'certificationRequestInfo/attributes';
|
4029 |
-
$attributes = &$this->_subArray($root, $pth, $create);
|
4030 |
-
|
4031 |
-
if (is_array($attributes)) {
|
4032 |
-
foreach ($attributes as $key => $value) {
|
4033 |
-
if ($value['type'] == 'pkcs-9-at-extensionRequest') {
|
4034 |
-
$path = "$pth/$key/value/0";
|
4035 |
-
break 2;
|
4036 |
-
}
|
4037 |
-
}
|
4038 |
-
if ($create) {
|
4039 |
-
$key = count($attributes);
|
4040 |
-
$attributes[] = array('type' => 'pkcs-9-at-extensionRequest', 'value' => array());
|
4041 |
-
$path = "$pth/$key/value/0";
|
4042 |
-
}
|
4043 |
-
}
|
4044 |
-
break;
|
4045 |
-
}
|
4046 |
-
|
4047 |
-
$extensions = &$this->_subArray($root, $path, $create);
|
4048 |
-
|
4049 |
-
if (!is_array($extensions)) {
|
4050 |
-
$false = false;
|
4051 |
-
return $false;
|
4052 |
-
}
|
4053 |
-
|
4054 |
-
return $extensions;
|
4055 |
-
}
|
4056 |
-
|
4057 |
-
/**
|
4058 |
-
* Remove an Extension
|
4059 |
-
*
|
4060 |
-
* @param string $id
|
4061 |
-
* @param string $path optional
|
4062 |
-
* @access private
|
4063 |
-
* @return bool
|
4064 |
-
*/
|
4065 |
-
function _removeExtension($id, $path = null)
|
4066 |
-
{
|
4067 |
-
$extensions = &$this->_extensions($this->currentCert, $path);
|
4068 |
-
|
4069 |
-
if (!is_array($extensions)) {
|
4070 |
-
return false;
|
4071 |
-
}
|
4072 |
-
|
4073 |
-
$result = false;
|
4074 |
-
foreach ($extensions as $key => $value) {
|
4075 |
-
if ($value['extnId'] == $id) {
|
4076 |
-
unset($extensions[$key]);
|
4077 |
-
$result = true;
|
4078 |
-
}
|
4079 |
-
}
|
4080 |
-
|
4081 |
-
$extensions = array_values($extensions);
|
4082 |
-
return $result;
|
4083 |
-
}
|
4084 |
-
|
4085 |
-
/**
|
4086 |
-
* Get an Extension
|
4087 |
-
*
|
4088 |
-
* Returns the extension if it exists and false if not
|
4089 |
-
*
|
4090 |
-
* @param string $id
|
4091 |
-
* @param array $cert optional
|
4092 |
-
* @param string $path optional
|
4093 |
-
* @access private
|
4094 |
-
* @return mixed
|
4095 |
-
*/
|
4096 |
-
function _getExtension($id, $cert = null, $path = null)
|
4097 |
-
{
|
4098 |
-
$extensions = $this->_extensions($cert, $path);
|
4099 |
-
|
4100 |
-
if (!is_array($extensions)) {
|
4101 |
-
return false;
|
4102 |
-
}
|
4103 |
-
|
4104 |
-
foreach ($extensions as $key => $value) {
|
4105 |
-
if ($value['extnId'] == $id) {
|
4106 |
-
return $value['extnValue'];
|
4107 |
-
}
|
4108 |
-
}
|
4109 |
-
|
4110 |
-
return false;
|
4111 |
-
}
|
4112 |
-
|
4113 |
-
/**
|
4114 |
-
* Returns a list of all extensions in use
|
4115 |
-
*
|
4116 |
-
* @param array $cert optional
|
4117 |
-
* @param string $path optional
|
4118 |
-
* @access private
|
4119 |
-
* @return array
|
4120 |
-
*/
|
4121 |
-
function _getExtensions($cert = null, $path = null)
|
4122 |
-
{
|
4123 |
-
$exts = $this->_extensions($cert, $path);
|
4124 |
-
$extensions = array();
|
4125 |
-
|
4126 |
-
if (is_array($exts)) {
|
4127 |
-
foreach ($exts as $extension) {
|
4128 |
-
$extensions[] = $extension['extnId'];
|
4129 |
-
}
|
4130 |
-
}
|
4131 |
-
|
4132 |
-
return $extensions;
|
4133 |
-
}
|
4134 |
-
|
4135 |
-
/**
|
4136 |
-
* Set an Extension
|
4137 |
-
*
|
4138 |
-
* @param string $id
|
4139 |
-
* @param mixed $value
|
4140 |
-
* @param bool $critical optional
|
4141 |
-
* @param bool $replace optional
|
4142 |
-
* @param string $path optional
|
4143 |
-
* @access private
|
4144 |
-
* @return bool
|
4145 |
-
*/
|
4146 |
-
function _setExtension($id, $value, $critical = false, $replace = true, $path = null)
|
4147 |
-
{
|
4148 |
-
$extensions = &$this->_extensions($this->currentCert, $path, true);
|
4149 |
-
|
4150 |
-
if (!is_array($extensions)) {
|
4151 |
-
return false;
|
4152 |
-
}
|
4153 |
-
|
4154 |
-
$newext = array('extnId' => $id, 'critical' => $critical, 'extnValue' => $value);
|
4155 |
-
|
4156 |
-
foreach ($extensions as $key => $value) {
|
4157 |
-
if ($value['extnId'] == $id) {
|
4158 |
-
if (!$replace) {
|
4159 |
-
return false;
|
4160 |
-
}
|
4161 |
-
|
4162 |
-
$extensions[$key] = $newext;
|
4163 |
-
return true;
|
4164 |
-
}
|
4165 |
-
}
|
4166 |
-
|
4167 |
-
$extensions[] = $newext;
|
4168 |
-
return true;
|
4169 |
-
}
|
4170 |
-
|
4171 |
-
/**
|
4172 |
-
* Remove a certificate, CSR or CRL Extension
|
4173 |
-
*
|
4174 |
-
* @param string $id
|
4175 |
-
* @access public
|
4176 |
-
* @return bool
|
4177 |
-
*/
|
4178 |
-
function removeExtension($id)
|
4179 |
-
{
|
4180 |
-
return $this->_removeExtension($id);
|
4181 |
-
}
|
4182 |
-
|
4183 |
-
/**
|
4184 |
-
* Get a certificate, CSR or CRL Extension
|
4185 |
-
*
|
4186 |
-
* Returns the extension if it exists and false if not
|
4187 |
-
*
|
4188 |
-
* @param string $id
|
4189 |
-
* @param array $cert optional
|
4190 |
-
* @access public
|
4191 |
-
* @return mixed
|
4192 |
-
*/
|
4193 |
-
function getExtension($id, $cert = null)
|
4194 |
-
{
|
4195 |
-
return $this->_getExtension($id, $cert);
|
4196 |
-
}
|
4197 |
-
|
4198 |
-
/**
|
4199 |
-
* Returns a list of all extensions in use in certificate, CSR or CRL
|
4200 |
-
*
|
4201 |
-
* @param array $cert optional
|
4202 |
-
* @access public
|
4203 |
-
* @return array
|
4204 |
-
*/
|
4205 |
-
function getExtensions($cert = null)
|
4206 |
-
{
|
4207 |
-
return $this->_getExtensions($cert);
|
4208 |
-
}
|
4209 |
-
|
4210 |
-
/**
|
4211 |
-
* Set a certificate, CSR or CRL Extension
|
4212 |
-
*
|
4213 |
-
* @param string $id
|
4214 |
-
* @param mixed $value
|
4215 |
-
* @param bool $critical optional
|
4216 |
-
* @param bool $replace optional
|
4217 |
-
* @access public
|
4218 |
-
* @return bool
|
4219 |
-
*/
|
4220 |
-
function setExtension($id, $value, $critical = false, $replace = true)
|
4221 |
-
{
|
4222 |
-
return $this->_setExtension($id, $value, $critical, $replace);
|
4223 |
-
}
|
4224 |
-
|
4225 |
-
/**
|
4226 |
-
* Remove a CSR attribute.
|
4227 |
-
*
|
4228 |
-
* @param string $id
|
4229 |
-
* @param int $disposition optional
|
4230 |
-
* @access public
|
4231 |
-
* @return bool
|
4232 |
-
*/
|
4233 |
-
function removeAttribute($id, $disposition = self::ATTR_ALL)
|
4234 |
-
{
|
4235 |
-
$attributes = &$this->_subArray($this->currentCert, 'certificationRequestInfo/attributes');
|
4236 |
-
|
4237 |
-
if (!is_array($attributes)) {
|
4238 |
-
return false;
|
4239 |
-
}
|
4240 |
-
|
4241 |
-
$result = false;
|
4242 |
-
foreach ($attributes as $key => $attribute) {
|
4243 |
-
if ($attribute['type'] == $id) {
|
4244 |
-
$n = count($attribute['value']);
|
4245 |
-
switch (true) {
|
4246 |
-
case $disposition == self::ATTR_APPEND:
|
4247 |
-
case $disposition == self::ATTR_REPLACE:
|
4248 |
-
return false;
|
4249 |
-
case $disposition >= $n:
|
4250 |
-
$disposition -= $n;
|
4251 |
-
break;
|
4252 |
-
case $disposition == self::ATTR_ALL:
|
4253 |
-
case $n == 1:
|
4254 |
-
unset($attributes[$key]);
|
4255 |
-
$result = true;
|
4256 |
-
break;
|
4257 |
-
default:
|
4258 |
-
unset($attributes[$key]['value'][$disposition]);
|
4259 |
-
$attributes[$key]['value'] = array_values($attributes[$key]['value']);
|
4260 |
-
$result = true;
|
4261 |
-
break;
|
4262 |
-
}
|
4263 |
-
if ($result && $disposition != self::ATTR_ALL) {
|
4264 |
-
break;
|
4265 |
-
}
|
4266 |
-
}
|
4267 |
-
}
|
4268 |
-
|
4269 |
-
$attributes = array_values($attributes);
|
4270 |
-
return $result;
|
4271 |
-
}
|
4272 |
-
|
4273 |
-
/**
|
4274 |
-
* Get a CSR attribute
|
4275 |
-
*
|
4276 |
-
* Returns the attribute if it exists and false if not
|
4277 |
-
*
|
4278 |
-
* @param string $id
|
4279 |
-
* @param int $disposition optional
|
4280 |
-
* @param array $csr optional
|
4281 |
-
* @access public
|
4282 |
-
* @return mixed
|
4283 |
-
*/
|
4284 |
-
function getAttribute($id, $disposition = self::ATTR_ALL, $csr = null)
|
4285 |
-
{
|
4286 |
-
if (empty($csr)) {
|
4287 |
-
$csr = $this->currentCert;
|
4288 |
-
}
|
4289 |
-
|
4290 |
-
$attributes = $this->_subArray($csr, 'certificationRequestInfo/attributes');
|
4291 |
-
|
4292 |
-
if (!is_array($attributes)) {
|
4293 |
-
return false;
|
4294 |
-
}
|
4295 |
-
|
4296 |
-
foreach ($attributes as $key => $attribute) {
|
4297 |
-
if ($attribute['type'] == $id) {
|
4298 |
-
$n = count($attribute['value']);
|
4299 |
-
switch (true) {
|
4300 |
-
case $disposition == self::ATTR_APPEND:
|
4301 |
-
case $disposition == self::ATTR_REPLACE:
|
4302 |
-
return false;
|
4303 |
-
case $disposition == self::ATTR_ALL:
|
4304 |
-
return $attribute['value'];
|
4305 |
-
case $disposition >= $n:
|
4306 |
-
$disposition -= $n;
|
4307 |
-
break;
|
4308 |
-
default:
|
4309 |
-
return $attribute['value'][$disposition];
|
4310 |
-
}
|
4311 |
-
}
|
4312 |
-
}
|
4313 |
-
|
4314 |
-
return false;
|
4315 |
-
}
|
4316 |
-
|
4317 |
-
/**
|
4318 |
-
* Returns a list of all CSR attributes in use
|
4319 |
-
*
|
4320 |
-
* @param array $csr optional
|
4321 |
-
* @access public
|
4322 |
-
* @return array
|
4323 |
-
*/
|
4324 |
-
function getAttributes($csr = null)
|
4325 |
-
{
|
4326 |
-
if (empty($csr)) {
|
4327 |
-
$csr = $this->currentCert;
|
4328 |
-
}
|
4329 |
-
|
4330 |
-
$attributes = $this->_subArray($csr, 'certificationRequestInfo/attributes');
|
4331 |
-
$attrs = array();
|
4332 |
-
|
4333 |
-
if (is_array($attributes)) {
|
4334 |
-
foreach ($attributes as $attribute) {
|
4335 |
-
$attrs[] = $attribute['type'];
|
4336 |
-
}
|
4337 |
-
}
|
4338 |
-
|
4339 |
-
return $attrs;
|
4340 |
-
}
|
4341 |
-
|
4342 |
-
/**
|
4343 |
-
* Set a CSR attribute
|
4344 |
-
*
|
4345 |
-
* @param string $id
|
4346 |
-
* @param mixed $value
|
4347 |
-
* @param bool $disposition optional
|
4348 |
-
* @access public
|
4349 |
-
* @return bool
|
4350 |
-
*/
|
4351 |
-
function setAttribute($id, $value, $disposition = self::ATTR_ALL)
|
4352 |
-
{
|
4353 |
-
$attributes = &$this->_subArray($this->currentCert, 'certificationRequestInfo/attributes', true);
|
4354 |
-
|
4355 |
-
if (!is_array($attributes)) {
|
4356 |
-
return false;
|
4357 |
-
}
|
4358 |
-
|
4359 |
-
switch ($disposition) {
|
4360 |
-
case self::ATTR_REPLACE:
|
4361 |
-
$disposition = self::ATTR_APPEND;
|
4362 |
-
case self::ATTR_ALL:
|
4363 |
-
$this->removeAttribute($id);
|
4364 |
-
break;
|
4365 |
-
}
|
4366 |
-
|
4367 |
-
foreach ($attributes as $key => $attribute) {
|
4368 |
-
if ($attribute['type'] == $id) {
|
4369 |
-
$n = count($attribute['value']);
|
4370 |
-
switch (true) {
|
4371 |
-
case $disposition == self::ATTR_APPEND:
|
4372 |
-
$last = $key;
|
4373 |
-
break;
|
4374 |
-
case $disposition >= $n:
|
4375 |
-
$disposition -= $n;
|
4376 |
-
break;
|
4377 |
-
default:
|
4378 |
-
$attributes[$key]['value'][$disposition] = $value;
|
4379 |
-
return true;
|
4380 |
-
}
|
4381 |
-
}
|
4382 |
-
}
|
4383 |
-
|
4384 |
-
switch (true) {
|
4385 |
-
case $disposition >= 0:
|
4386 |
-
return false;
|
4387 |
-
case isset($last):
|
4388 |
-
$attributes[$last]['value'][] = $value;
|
4389 |
-
break;
|
4390 |
-
default:
|
4391 |
-
$attributes[] = array('type' => $id, 'value' => $disposition == self::ATTR_ALL ? $value: array($value));
|
4392 |
-
break;
|
4393 |
-
}
|
4394 |
-
|
4395 |
-
return true;
|
4396 |
-
}
|
4397 |
-
|
4398 |
-
/**
|
4399 |
-
* Sets the subject key identifier
|
4400 |
-
*
|
4401 |
-
* This is used by the id-ce-authorityKeyIdentifier and the id-ce-subjectKeyIdentifier extensions.
|
4402 |
-
*
|
4403 |
-
* @param string $value
|
4404 |
-
* @access public
|
4405 |
-
*/
|
4406 |
-
function setKeyIdentifier($value)
|
4407 |
-
{
|
4408 |
-
if (empty($value)) {
|
4409 |
-
unset($this->currentKeyIdentifier);
|
4410 |
-
} else {
|
4411 |
-
$this->currentKeyIdentifier = base64_encode($value);
|
4412 |
-
}
|
4413 |
-
}
|
4414 |
-
|
4415 |
-
/**
|
4416 |
-
* Compute a public key identifier.
|
4417 |
-
*
|
4418 |
-
* Although key identifiers may be set to any unique value, this function
|
4419 |
-
* computes key identifiers from public key according to the two
|
4420 |
-
* recommended methods (4.2.1.2 RFC 3280).
|
4421 |
-
* Highly polymorphic: try to accept all possible forms of key:
|
4422 |
-
* - Key object
|
4423 |
-
* - \phpseclib\File\X509 object with public or private key defined
|
4424 |
-
* - Certificate or CSR array
|
4425 |
-
* - \phpseclib\File\ASN1\Element object
|
4426 |
-
* - PEM or DER string
|
4427 |
-
*
|
4428 |
-
* @param mixed $key optional
|
4429 |
-
* @param int $method optional
|
4430 |
-
* @access public
|
4431 |
-
* @return string binary key identifier
|
4432 |
-
*/
|
4433 |
-
function computeKeyIdentifier($key = null, $method = 1)
|
4434 |
-
{
|
4435 |
-
if (is_null($key)) {
|
4436 |
-
$key = $this;
|
4437 |
-
}
|
4438 |
-
|
4439 |
-
switch (true) {
|
4440 |
-
case is_string($key):
|
4441 |
-
break;
|
4442 |
-
case is_array($key) && isset($key['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']):
|
4443 |
-
return $this->computeKeyIdentifier($key['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'], $method);
|
4444 |
-
case is_array($key) && isset($key['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']):
|
4445 |
-
return $this->computeKeyIdentifier($key['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'], $method);
|
4446 |
-
case !is_object($key):
|
4447 |
-
return false;
|
4448 |
-
case $key instanceof Element:
|
4449 |
-
// Assume the element is a bitstring-packed key.
|
4450 |
-
$asn1 = new ASN1();
|
4451 |
-
$decoded = $asn1->decodeBER($key->element);
|
4452 |
-
if (empty($decoded)) {
|
4453 |
-
return false;
|
4454 |
-
}
|
4455 |
-
$raw = $asn1->asn1map($decoded[0], array('type' => ASN1::TYPE_BIT_STRING));
|
4456 |
-
if (empty($raw)) {
|
4457 |
-
return false;
|
4458 |
-
}
|
4459 |
-
$raw = base64_decode($raw);
|
4460 |
-
// If the key is private, compute identifier from its corresponding public key.
|
4461 |
-
$key = new RSA();
|
4462 |
-
if (!$key->loadKey($raw)) {
|
4463 |
-
return false; // Not an unencrypted RSA key.
|
4464 |
-
}
|
4465 |
-
if ($key->getPrivateKey() !== false) { // If private.
|
4466 |
-
return $this->computeKeyIdentifier($key, $method);
|
4467 |
-
}
|
4468 |
-
$key = $raw; // Is a public key.
|
4469 |
-
break;
|
4470 |
-
case $key instanceof X509:
|
4471 |
-
if (isset($key->publicKey)) {
|
4472 |
-
return $this->computeKeyIdentifier($key->publicKey, $method);
|
4473 |
-
}
|
4474 |
-
if (isset($key->privateKey)) {
|
4475 |
-
return $this->computeKeyIdentifier($key->privateKey, $method);
|
4476 |
-
}
|
4477 |
-
if (isset($key->currentCert['tbsCertificate']) || isset($key->currentCert['certificationRequestInfo'])) {
|
4478 |
-
return $this->computeKeyIdentifier($key->currentCert, $method);
|
4479 |
-
}
|
4480 |
-
return false;
|
4481 |
-
default: // Should be a key object (i.e.: \phpseclib\Crypt\RSA).
|
4482 |
-
$key = $key->getPublicKey(RSA::PUBLIC_FORMAT_PKCS1);
|
4483 |
-
break;
|
4484 |
-
}
|
4485 |
-
|
4486 |
-
// If in PEM format, convert to binary.
|
4487 |
-
$key = $this->_extractBER($key);
|
4488 |
-
|
4489 |
-
// Now we have the key string: compute its sha-1 sum.
|
4490 |
-
$hash = new Hash('sha1');
|
4491 |
-
$hash = $hash->hash($key);
|
4492 |
-
|
4493 |
-
if ($method == 2) {
|
4494 |
-
$hash = substr($hash, -8);
|
4495 |
-
$hash[0] = chr((ord($hash[0]) & 0x0F) | 0x40);
|
4496 |
-
}
|
4497 |
-
|
4498 |
-
return $hash;
|
4499 |
-
}
|
4500 |
-
|
4501 |
-
/**
|
4502 |
-
* Format a public key as appropriate
|
4503 |
-
*
|
4504 |
-
* @access private
|
4505 |
-
* @return array
|
4506 |
-
*/
|
4507 |
-
function _formatSubjectPublicKey()
|
4508 |
-
{
|
4509 |
-
if ($this->publicKey instanceof RSA) {
|
4510 |
-
// the following two return statements do the same thing. i dunno.. i just prefer the later for some reason.
|
4511 |
-
// the former is a good example of how to do fuzzing on the public key
|
4512 |
-
//return new Element(base64_decode(preg_replace('#-.+-|[\r\n]#', '', $this->publicKey->getPublicKey())));
|
4513 |
-
return array(
|
4514 |
-
'algorithm' => array('algorithm' => 'rsaEncryption'),
|
4515 |
-
'subjectPublicKey' => $this->publicKey->getPublicKey(RSA::PUBLIC_FORMAT_PKCS1)
|
4516 |
-
);
|
4517 |
-
}
|
4518 |
-
|
4519 |
-
return false;
|
4520 |
-
}
|
4521 |
-
|
4522 |
-
/**
|
4523 |
-
* Set the domain name's which the cert is to be valid for
|
4524 |
-
*
|
4525 |
-
* @access public
|
4526 |
-
* @return array
|
4527 |
-
*/
|
4528 |
-
function setDomain()
|
4529 |
-
{
|
4530 |
-
$this->domains = func_get_args();
|
4531 |
-
$this->removeDNProp('id-at-commonName');
|
4532 |
-
$this->setDNProp('id-at-commonName', $this->domains[0]);
|
4533 |
-
}
|
4534 |
-
|
4535 |
-
/**
|
4536 |
-
* Set the IP Addresses's which the cert is to be valid for
|
4537 |
-
*
|
4538 |
-
* @access public
|
4539 |
-
* @param string $ipAddress optional
|
4540 |
-
*/
|
4541 |
-
function setIPAddress()
|
4542 |
-
{
|
4543 |
-
$this->ipAddresses = func_get_args();
|
4544 |
-
/*
|
4545 |
-
if (!isset($this->domains)) {
|
4546 |
-
$this->removeDNProp('id-at-commonName');
|
4547 |
-
$this->setDNProp('id-at-commonName', $this->ipAddresses[0]);
|
4548 |
-
}
|
4549 |
-
*/
|
4550 |
-
}
|
4551 |
-
|
4552 |
-
/**
|
4553 |
-
* Helper function to build domain array
|
4554 |
-
*
|
4555 |
-
* @access private
|
4556 |
-
* @param string $domain
|
4557 |
-
* @return array
|
4558 |
-
*/
|
4559 |
-
function _dnsName($domain)
|
4560 |
-
{
|
4561 |
-
return array('dNSName' => $domain);
|
4562 |
-
}
|
4563 |
-
|
4564 |
-
/**
|
4565 |
-
* Helper function to build IP Address array
|
4566 |
-
*
|
4567 |
-
* (IPv6 is not currently supported)
|
4568 |
-
*
|
4569 |
-
* @access private
|
4570 |
-
* @param string $address
|
4571 |
-
* @return array
|
4572 |
-
*/
|
4573 |
-
function _iPAddress($address)
|
4574 |
-
{
|
4575 |
-
return array('iPAddress' => $address);
|
4576 |
-
}
|
4577 |
-
|
4578 |
-
/**
|
4579 |
-
* Get the index of a revoked certificate.
|
4580 |
-
*
|
4581 |
-
* @param array $rclist
|
4582 |
-
* @param string $serial
|
4583 |
-
* @param bool $create optional
|
4584 |
-
* @access private
|
4585 |
-
* @return int|false
|
4586 |
-
*/
|
4587 |
-
function _revokedCertificate(&$rclist, $serial, $create = false)
|
4588 |
-
{
|
4589 |
-
$serial = new BigInteger($serial);
|
4590 |
-
|
4591 |
-
foreach ($rclist as $i => $rc) {
|
4592 |
-
if (!($serial->compare($rc['userCertificate']))) {
|
4593 |
-
return $i;
|
4594 |
-
}
|
4595 |
-
}
|
4596 |
-
|
4597 |
-
if (!$create) {
|
4598 |
-
return false;
|
4599 |
-
}
|
4600 |
-
|
4601 |
-
$i = count($rclist);
|
4602 |
-
$revocationDate = new DateTime('now', new DateTimeZone(@date_default_timezone_get()));
|
4603 |
-
$rclist[] = array('userCertificate' => $serial,
|
4604 |
-
'revocationDate' => $this->_timeField($revocationDate->format('D, d M Y H:i:s O')));
|
4605 |
-
return $i;
|
4606 |
-
}
|
4607 |
-
|
4608 |
-
/**
|
4609 |
-
* Revoke a certificate.
|
4610 |
-
*
|
4611 |
-
* @param string $serial
|
4612 |
-
* @param string $date optional
|
4613 |
-
* @access public
|
4614 |
-
* @return bool
|
4615 |
-
*/
|
4616 |
-
function revoke($serial, $date = null)
|
4617 |
-
{
|
4618 |
-
if (isset($this->currentCert['tbsCertList'])) {
|
4619 |
-
if (is_array($rclist = &$this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates', true))) {
|
4620 |
-
if ($this->_revokedCertificate($rclist, $serial) === false) { // If not yet revoked
|
4621 |
-
if (($i = $this->_revokedCertificate($rclist, $serial, true)) !== false) {
|
4622 |
-
if (!empty($date)) {
|
4623 |
-
$rclist[$i]['revocationDate'] = $this->_timeField($date);
|
4624 |
-
}
|
4625 |
-
|
4626 |
-
return true;
|
4627 |
-
}
|
4628 |
-
}
|
4629 |
-
}
|
4630 |
-
}
|
4631 |
-
|
4632 |
-
return false;
|
4633 |
-
}
|
4634 |
-
|
4635 |
-
/**
|
4636 |
-
* Unrevoke a certificate.
|
4637 |
-
*
|
4638 |
-
* @param string $serial
|
4639 |
-
* @access public
|
4640 |
-
* @return bool
|
4641 |
-
*/
|
4642 |
-
function unrevoke($serial)
|
4643 |
-
{
|
4644 |
-
if (is_array($rclist = &$this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) {
|
4645 |
-
if (($i = $this->_revokedCertificate($rclist, $serial)) !== false) {
|
4646 |
-
unset($rclist[$i]);
|
4647 |
-
$rclist = array_values($rclist);
|
4648 |
-
return true;
|
4649 |
-
}
|
4650 |
-
}
|
4651 |
-
|
4652 |
-
return false;
|
4653 |
-
}
|
4654 |
-
|
4655 |
-
/**
|
4656 |
-
* Get a revoked certificate.
|
4657 |
-
*
|
4658 |
-
* @param string $serial
|
4659 |
-
* @access public
|
4660 |
-
* @return mixed
|
4661 |
-
*/
|
4662 |
-
function getRevoked($serial)
|
4663 |
-
{
|
4664 |
-
if (is_array($rclist = $this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) {
|
4665 |
-
if (($i = $this->_revokedCertificate($rclist, $serial)) !== false) {
|
4666 |
-
return $rclist[$i];
|
4667 |
-
}
|
4668 |
-
}
|
4669 |
-
|
4670 |
-
return false;
|
4671 |
-
}
|
4672 |
-
|
4673 |
-
/**
|
4674 |
-
* List revoked certificates
|
4675 |
-
*
|
4676 |
-
* @param array $crl optional
|
4677 |
-
* @access public
|
4678 |
-
* @return array
|
4679 |
-
*/
|
4680 |
-
function listRevoked($crl = null)
|
4681 |
-
{
|
4682 |
-
if (!isset($crl)) {
|
4683 |
-
$crl = $this->currentCert;
|
4684 |
-
}
|
4685 |
-
|
4686 |
-
if (!isset($crl['tbsCertList'])) {
|
4687 |
-
return false;
|
4688 |
-
}
|
4689 |
-
|
4690 |
-
$result = array();
|
4691 |
-
|
4692 |
-
if (is_array($rclist = $this->_subArray($crl, 'tbsCertList/revokedCertificates'))) {
|
4693 |
-
foreach ($rclist as $rc) {
|
4694 |
-
$result[] = $rc['userCertificate']->toString();
|
4695 |
-
}
|
4696 |
-
}
|
4697 |
-
|
4698 |
-
return $result;
|
4699 |
-
}
|
4700 |
-
|
4701 |
-
/**
|
4702 |
-
* Remove a Revoked Certificate Extension
|
4703 |
-
*
|
4704 |
-
* @param string $serial
|
4705 |
-
* @param string $id
|
4706 |
-
* @access public
|
4707 |
-
* @return bool
|
4708 |
-
*/
|
4709 |
-
function removeRevokedCertificateExtension($serial, $id)
|
4710 |
-
{
|
4711 |
-
if (is_array($rclist = &$this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) {
|
4712 |
-
if (($i = $this->_revokedCertificate($rclist, $serial)) !== false) {
|
4713 |
-
return $this->_removeExtension($id, "tbsCertList/revokedCertificates/$i/crlEntryExtensions");
|
4714 |
-
}
|
4715 |
-
}
|
4716 |
-
|
4717 |
-
return false;
|
4718 |
-
}
|
4719 |
-
|
4720 |
-
/**
|
4721 |
-
* Get a Revoked Certificate Extension
|
4722 |
-
*
|
4723 |
-
* Returns the extension if it exists and false if not
|
4724 |
-
*
|
4725 |
-
* @param string $serial
|
4726 |
-
* @param string $id
|
4727 |
-
* @param array $crl optional
|
4728 |
-
* @access public
|
4729 |
-
* @return mixed
|
4730 |
-
*/
|
4731 |
-
function getRevokedCertificateExtension($serial, $id, $crl = null)
|
4732 |
-
{
|
4733 |
-
if (!isset($crl)) {
|
4734 |
-
$crl = $this->currentCert;
|
4735 |
-
}
|
4736 |
-
|
4737 |
-
if (is_array($rclist = $this->_subArray($crl, 'tbsCertList/revokedCertificates'))) {
|
4738 |
-
if (($i = $this->_revokedCertificate($rclist, $serial)) !== false) {
|
4739 |
-
return $this->_getExtension($id, $crl, "tbsCertList/revokedCertificates/$i/crlEntryExtensions");
|
4740 |
-
}
|
4741 |
-
}
|
4742 |
-
|
4743 |
-
return false;
|
4744 |
-
}
|
4745 |
-
|
4746 |
-
/**
|
4747 |
-
* Returns a list of all extensions in use for a given revoked certificate
|
4748 |
-
*
|
4749 |
-
* @param string $serial
|
4750 |
-
* @param array $crl optional
|
4751 |
-
* @access public
|
4752 |
-
* @return array
|
4753 |
-
*/
|
4754 |
-
function getRevokedCertificateExtensions($serial, $crl = null)
|
4755 |
-
{
|
4756 |
-
if (!isset($crl)) {
|
4757 |
-
$crl = $this->currentCert;
|
4758 |
-
}
|
4759 |
-
|
4760 |
-
if (is_array($rclist = $this->_subArray($crl, 'tbsCertList/revokedCertificates'))) {
|
4761 |
-
if (($i = $this->_revokedCertificate($rclist, $serial)) !== false) {
|
4762 |
-
return $this->_getExtensions($crl, "tbsCertList/revokedCertificates/$i/crlEntryExtensions");
|
4763 |
-
}
|
4764 |
-
}
|
4765 |
-
|
4766 |
-
return false;
|
4767 |
-
}
|
4768 |
-
|
4769 |
-
/**
|
4770 |
-
* Set a Revoked Certificate Extension
|
4771 |
-
*
|
4772 |
-
* @param string $serial
|
4773 |
-
* @param string $id
|
4774 |
-
* @param mixed $value
|
4775 |
-
* @param bool $critical optional
|
4776 |
-
* @param bool $replace optional
|
4777 |
-
* @access public
|
4778 |
-
* @return bool
|
4779 |
-
*/
|
4780 |
-
function setRevokedCertificateExtension($serial, $id, $value, $critical = false, $replace = true)
|
4781 |
-
{
|
4782 |
-
if (isset($this->currentCert['tbsCertList'])) {
|
4783 |
-
if (is_array($rclist = &$this->_subArray($this->currentCert, 'tbsCertList/revokedCertificates', true))) {
|
4784 |
-
if (($i = $this->_revokedCertificate($rclist, $serial, true)) !== false) {
|
4785 |
-
return $this->_setExtension($id, $value, $critical, $replace, "tbsCertList/revokedCertificates/$i/crlEntryExtensions");
|
4786 |
-
}
|
4787 |
-
}
|
4788 |
-
}
|
4789 |
-
|
4790 |
-
return false;
|
4791 |
-
}
|
4792 |
-
|
4793 |
-
/**
|
4794 |
-
* Extract raw BER from Base64 encoding
|
4795 |
-
*
|
4796 |
-
* @access private
|
4797 |
-
* @param string $str
|
4798 |
-
* @return string
|
4799 |
-
*/
|
4800 |
-
function _extractBER($str)
|
4801 |
-
{
|
4802 |
-
/* X.509 certs are assumed to be base64 encoded but sometimes they'll have additional things in them
|
4803 |
-
* above and beyond the ceritificate.
|
4804 |
-
* ie. some may have the following preceding the -----BEGIN CERTIFICATE----- line:
|
4805 |
-
*
|
4806 |
-
* Bag Attributes
|
4807 |
-
* localKeyID: 01 00 00 00
|
4808 |
-
* subject=/O=organization/OU=org unit/CN=common name
|
4809 |
-
* issuer=/O=organization/CN=common name
|
4810 |
-
*/
|
4811 |
-
$temp = preg_replace('#.*?^-+[^-]+-+[\r\n ]*$#ms', '', $str, 1);
|
4812 |
-
// remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff
|
4813 |
-
$temp = preg_replace('#-+[^-]+-+#', '', $temp);
|
4814 |
-
// remove new lines
|
4815 |
-
$temp = str_replace(array("\r", "\n", ' '), '', $temp);
|
4816 |
-
$temp = preg_match('#^[a-zA-Z\d/+]*={0,2}$#', $temp) ? base64_decode($temp) : false;
|
4817 |
-
return $temp != false ? $temp : $str;
|
4818 |
-
}
|
4819 |
-
|
4820 |
-
/**
|
4821 |
-
* Returns the OID corresponding to a name
|
4822 |
-
*
|
4823 |
-
* What's returned in the associative array returned by loadX509() (or load*()) is either a name or an OID if
|
4824 |
-
* no OID to name mapping is available. The problem with this is that what may be an unmapped OID in one version
|
4825 |
-
* of phpseclib may not be unmapped in the next version, so apps that are looking at this OID may not be able
|
4826 |
-
* to work from version to version.
|
4827 |
-
*
|
4828 |
-
* This method will return the OID if a name is passed to it and if no mapping is avialable it'll assume that
|
4829 |
-
* what's being passed to it already is an OID and return that instead. A few examples.
|
4830 |
-
*
|
4831 |
-
* getOID('2.16.840.1.101.3.4.2.1') == '2.16.840.1.101.3.4.2.1'
|
4832 |
-
* getOID('id-sha256') == '2.16.840.1.101.3.4.2.1'
|
4833 |
-
* getOID('zzz') == 'zzz'
|
4834 |
-
*
|
4835 |
-
* @access public
|
4836 |
-
* @return string
|
4837 |
-
*/
|
4838 |
-
function getOID($name)
|
4839 |
-
{
|
4840 |
-
static $reverseMap;
|
4841 |
-
if (!isset($reverseMap)) {
|
4842 |
-
$reverseMap = array_flip($this->oids);
|
4843 |
-
}
|
4844 |
-
return isset($reverseMap[$name]) ? $reverseMap[$name] : $name;
|
4845 |
-
}
|
4846 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/phpseclib/phpseclib/phpseclib/Net/SCP.php
DELETED
@@ -1,337 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Pure-PHP implementation of SCP.
|
5 |
-
*
|
6 |
-
* PHP version 5
|
7 |
-
*
|
8 |
-
* The API for this library is modeled after the API from PHP's {@link http://php.net/book.ftp FTP extension}.
|
9 |
-
*
|
10 |
-
* Here's a short example of how to use this library:
|
11 |
-
* <code>
|
12 |
-
* <?php
|
13 |
-
* include 'vendor/autoload.php';
|
14 |
-
*
|
15 |
-
* $ssh = new \phpseclib\Net\SSH2('www.domain.tld');
|
16 |
-
* if (!$ssh->login('username', 'password')) {
|
17 |
-
* exit('bad login');
|
18 |
-
* }
|
19 |
-
* $scp = new \phpseclib\Net\SCP($ssh);
|
20 |
-
*
|
21 |
-
* $scp->put('abcd', str_repeat('x', 1024*1024));
|
22 |
-
* ?>
|
23 |
-
* </code>
|
24 |
-
*
|
25 |
-
* @category Net
|
26 |
-
* @package SCP
|
27 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
28 |
-
* @copyright 2010 Jim Wigginton
|
29 |
-
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
30 |
-
* @link http://phpseclib.sourceforge.net
|
31 |
-
*/
|
32 |
-
|
33 |
-
namespace phpseclib\Net;
|
34 |
-
|
35 |
-
/**
|
36 |
-
* Pure-PHP implementations of SCP.
|
37 |
-
*
|
38 |
-
* @package SCP
|
39 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
40 |
-
* @access public
|
41 |
-
*/
|
42 |
-
class SCP
|
43 |
-
{
|
44 |
-
/**#@+
|
45 |
-
* @access public
|
46 |
-
* @see \phpseclib\Net\SCP::put()
|
47 |
-
*/
|
48 |
-
/**
|
49 |
-
* Reads data from a local file.
|
50 |
-
*/
|
51 |
-
const SOURCE_LOCAL_FILE = 1;
|
52 |
-
/**
|
53 |
-
* Reads data from a string.
|
54 |
-
*/
|
55 |
-
const SOURCE_STRING = 2;
|
56 |
-
/**#@-*/
|
57 |
-
|
58 |
-
/**#@+
|
59 |
-
* @access private
|
60 |
-
* @see \phpseclib\Net\SCP::_send()
|
61 |
-
* @see \phpseclib\Net\SCP::_receive()
|
62 |
-
*/
|
63 |
-
/**
|
64 |
-
* SSH1 is being used.
|
65 |
-
*/
|
66 |
-
const MODE_SSH1 = 1;
|
67 |
-
/**
|
68 |
-
* SSH2 is being used.
|
69 |
-
*/
|
70 |
-
const MODE_SSH2 = 2;
|
71 |
-
/**#@-*/
|
72 |
-
|
73 |
-
/**
|
74 |
-
* SSH Object
|
75 |
-
*
|
76 |
-
* @var object
|
77 |
-
* @access private
|
78 |
-
*/
|
79 |
-
var $ssh;
|
80 |
-
|
81 |
-
/**
|
82 |
-
* Packet Size
|
83 |
-
*
|
84 |
-
* @var int
|
85 |
-
* @access private
|
86 |
-
*/
|
87 |
-
var $packet_size;
|
88 |
-
|
89 |
-
/**
|
90 |
-
* Mode
|
91 |
-
*
|
92 |
-
* @var int
|
93 |
-
* @access private
|
94 |
-
*/
|
95 |
-
var $mode;
|
96 |
-
|
97 |
-
/**
|
98 |
-
* Default Constructor.
|
99 |
-
*
|
100 |
-
* Connects to an SSH server
|
101 |
-
*
|
102 |
-
* @param \phpseclib\Net\SSH1|\phpseclib\Net\SSH2 $ssh
|
103 |
-
* @return \phpseclib\Net\SCP
|
104 |
-
* @access public
|
105 |
-
*/
|
106 |
-
function __construct($ssh)
|
107 |
-
{
|
108 |
-
if ($ssh instanceof SSH2) {
|
109 |
-
$this->mode = self::MODE_SSH2;
|
110 |
-
} elseif ($ssh instanceof SSH1) {
|
111 |
-
$this->packet_size = 50000;
|
112 |
-
$this->mode = self::MODE_SSH1;
|
113 |
-
} else {
|
114 |
-
return;
|
115 |
-
}
|
116 |
-
|
117 |
-
$this->ssh = $ssh;
|
118 |
-
}
|
119 |
-
|
120 |
-
/**
|
121 |
-
* Uploads a file to the SCP server.
|
122 |
-
*
|
123 |
-
* By default, \phpseclib\Net\SCP::put() does not read from the local filesystem. $data is dumped directly into $remote_file.
|
124 |
-
* So, for example, if you set $data to 'filename.ext' and then do \phpseclib\Net\SCP::get(), you will get a file, twelve bytes
|
125 |
-
* long, containing 'filename.ext' as its contents.
|
126 |
-
*
|
127 |
-
* Setting $mode to self::SOURCE_LOCAL_FILE will change the above behavior. With self::SOURCE_LOCAL_FILE, $remote_file will
|
128 |
-
* contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how
|
129 |
-
* large $remote_file will be, as well.
|
130 |
-
*
|
131 |
-
* Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take
|
132 |
-
* care of that, yourself.
|
133 |
-
*
|
134 |
-
* @param string $remote_file
|
135 |
-
* @param string $data
|
136 |
-
* @param int $mode
|
137 |
-
* @param callable $callback
|
138 |
-
* @return bool
|
139 |
-
* @access public
|
140 |
-
*/
|
141 |
-
function put($remote_file, $data, $mode = self::SOURCE_STRING, $callback = null)
|
142 |
-
{
|
143 |
-
if (!isset($this->ssh)) {
|
144 |
-
return false;
|
145 |
-
}
|
146 |
-
|
147 |
-
if (!$this->ssh->exec('scp -t ' . escapeshellarg($remote_file), false)) { // -t = to
|
148 |
-
return false;
|
149 |
-
}
|
150 |
-
|
151 |
-
$temp = $this->_receive();
|
152 |
-
if ($temp !== chr(0)) {
|
153 |
-
return false;
|
154 |
-
}
|
155 |
-
|
156 |
-
if ($this->mode == self::MODE_SSH2) {
|
157 |
-
$this->packet_size = $this->ssh->packet_size_client_to_server[SSH2::CHANNEL_EXEC] - 4;
|
158 |
-
}
|
159 |
-
|
160 |
-
$remote_file = basename($remote_file);
|
161 |
-
|
162 |
-
if ($mode == self::SOURCE_STRING) {
|
163 |
-
$size = strlen($data);
|
164 |
-
} else {
|
165 |
-
if (!is_file($data)) {
|
166 |
-
user_error("$data is not a valid file", E_USER_NOTICE);
|
167 |
-
return false;
|
168 |
-
}
|
169 |
-
|
170 |
-
$fp = @fopen($data, 'rb');
|
171 |
-
if (!$fp) {
|
172 |
-
return false;
|
173 |
-
}
|
174 |
-
$size = filesize($data);
|
175 |
-
}
|
176 |
-
|
177 |
-
$this->_send('C0644 ' . $size . ' ' . $remote_file . "\n");
|
178 |
-
|
179 |
-
$temp = $this->_receive();
|
180 |
-
if ($temp !== chr(0)) {
|
181 |
-
return false;
|
182 |
-
}
|
183 |
-
|
184 |
-
$sent = 0;
|
185 |
-
while ($sent < $size) {
|
186 |
-
$temp = $mode & self::SOURCE_STRING ? substr($data, $sent, $this->packet_size) : fread($fp, $this->packet_size);
|
187 |
-
$this->_send($temp);
|
188 |
-
$sent+= strlen($temp);
|
189 |
-
|
190 |
-
if (is_callable($callback)) {
|
191 |
-
call_user_func($callback, $sent);
|
192 |
-
}
|
193 |
-
}
|
194 |
-
$this->_close();
|
195 |
-
|
196 |
-
if ($mode != self::SOURCE_STRING) {
|
197 |
-
fclose($fp);
|
198 |
-
}
|
199 |
-
|
200 |
-
return true;
|
201 |
-
}
|
202 |
-
|
203 |
-
/**
|
204 |
-
* Downloads a file from the SCP server.
|
205 |
-
*
|
206 |
-
* Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if
|
207 |
-
* the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the
|
208 |
-
* operation
|
209 |
-
*
|
210 |
-
* @param string $remote_file
|
211 |
-
* @param string $local_file
|
212 |
-
* @return mixed
|
213 |
-
* @access public
|
214 |
-
*/
|
215 |
-
function get($remote_file, $local_file = false)
|
216 |
-
{
|
217 |
-
if (!isset($this->ssh)) {
|
218 |
-
return false;
|
219 |
-
}
|
220 |
-
|
221 |
-
if (!$this->ssh->exec('scp -f ' . escapeshellarg($remote_file), false)) { // -f = from
|
222 |
-
return false;
|
223 |
-
}
|
224 |
-
|
225 |
-
$this->_send("\0");
|
226 |
-
|
227 |
-
if (!preg_match('#(?<perms>[^ ]+) (?<size>\d+) (?<name>.+)#', rtrim($this->_receive()), $info)) {
|
228 |
-
return false;
|
229 |
-
}
|
230 |
-
|
231 |
-
$this->_send("\0");
|
232 |
-
|
233 |
-
$size = 0;
|
234 |
-
|
235 |
-
if ($local_file !== false) {
|
236 |
-
$fp = @fopen($local_file, 'wb');
|
237 |
-
if (!$fp) {
|
238 |
-
return false;
|
239 |
-
}
|
240 |
-
}
|
241 |
-
|
242 |
-
$content = '';
|
243 |
-
while ($size < $info['size']) {
|
244 |
-
$data = $this->_receive();
|
245 |
-
// SCP usually seems to split stuff out into 16k chunks
|
246 |
-
$size+= strlen($data);
|
247 |
-
|
248 |
-
if ($local_file === false) {
|
249 |
-
$content.= $data;
|
250 |
-
} else {
|
251 |
-
fputs($fp, $data);
|
252 |
-
}
|
253 |
-
}
|
254 |
-
|
255 |
-
$this->_close();
|
256 |
-
|
257 |
-
if ($local_file !== false) {
|
258 |
-
fclose($fp);
|
259 |
-
return true;
|
260 |
-
}
|
261 |
-
|
262 |
-
return $content;
|
263 |
-
}
|
264 |
-
|
265 |
-
/**
|
266 |
-
* Sends a packet to an SSH server
|
267 |
-
*
|
268 |
-
* @param string $data
|
269 |
-
* @access private
|
270 |
-
*/
|
271 |
-
function _send($data)
|
272 |
-
{
|
273 |
-
switch ($this->mode) {
|
274 |
-
case self::MODE_SSH2:
|
275 |
-
$this->ssh->_send_channel_packet(SSH2::CHANNEL_EXEC, $data);
|
276 |
-
break;
|
277 |
-
case self::MODE_SSH1:
|
278 |
-
$data = pack('CNa*', NET_SSH1_CMSG_STDIN_DATA, strlen($data), $data);
|
279 |
-
$this->ssh->_send_binary_packet($data);
|
280 |
-
}
|
281 |
-
}
|
282 |
-
|
283 |
-
/**
|
284 |
-
* Receives a packet from an SSH server
|
285 |
-
*
|
286 |
-
* @return string
|
287 |
-
* @access private
|
288 |
-
*/
|
289 |
-
function _receive()
|
290 |
-
{
|
291 |
-
switch ($this->mode) {
|
292 |
-
case self::MODE_SSH2:
|
293 |
-
return $this->ssh->_get_channel_packet(SSH2::CHANNEL_EXEC, true);
|
294 |
-
case self::MODE_SSH1:
|
295 |
-
if (!$this->ssh->bitmap) {
|
296 |
-
return false;
|
297 |
-
}
|
298 |
-
while (true) {
|
299 |
-
$response = $this->ssh->_get_binary_packet();
|
300 |
-
switch ($response[SSH1::RESPONSE_TYPE]) {
|
301 |
-
case NET_SSH1_SMSG_STDOUT_DATA:
|
302 |
-
if (strlen($response[SSH1::RESPONSE_DATA]) < 4) {
|
303 |
-
return false;
|
304 |
-
}
|
305 |
-
extract(unpack('Nlength', $response[SSH1::RESPONSE_DATA]));
|
306 |
-
return $this->ssh->_string_shift($response[SSH1::RESPONSE_DATA], $length);
|
307 |
-
case NET_SSH1_SMSG_STDERR_DATA:
|
308 |
-
break;
|
309 |
-
case NET_SSH1_SMSG_EXITSTATUS:
|
310 |
-
$this->ssh->_send_binary_packet(chr(NET_SSH1_CMSG_EXIT_CONFIRMATION));
|
311 |
-
fclose($this->ssh->fsock);
|
312 |
-
$this->ssh->bitmap = 0;
|
313 |
-
return false;
|
314 |
-
default:
|
315 |
-
user_error('Unknown packet received', E_USER_NOTICE);
|
316 |
-
return false;
|
317 |
-
}
|
318 |
-
}
|
319 |
-
}
|
320 |
-
}
|
321 |
-
|
322 |
-
/**
|
323 |
-
* Closes the connection to an SSH server
|
324 |
-
*
|
325 |
-
* @access private
|
326 |
-
*/
|
327 |
-
function _close()
|
328 |
-
{
|
329 |
-
switch ($this->mode) {
|
330 |
-
case self::MODE_SSH2:
|
331 |
-
$this->ssh->_close_channel(SSH2::CHANNEL_EXEC, true);
|
332 |
-
break;
|
333 |
-
case self::MODE_SSH1:
|
334 |
-
$this->ssh->disconnect();
|
335 |
-
}
|
336 |
-
}
|
337 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php
DELETED
@@ -1,3104 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Pure-PHP implementation of SFTP.
|
5 |
-
*
|
6 |
-
* PHP version 5
|
7 |
-
*
|
8 |
-
* Currently only supports SFTPv2 and v3, which, according to wikipedia.org, "is the most widely used version,
|
9 |
-
* implemented by the popular OpenSSH SFTP server". If you want SFTPv4/5/6 support, provide me with access
|
10 |
-
* to an SFTPv4/5/6 server.
|
11 |
-
*
|
12 |
-
* The API for this library is modeled after the API from PHP's {@link http://php.net/book.ftp FTP extension}.
|
13 |
-
*
|
14 |
-
* Here's a short example of how to use this library:
|
15 |
-
* <code>
|
16 |
-
* <?php
|
17 |
-
* include 'vendor/autoload.php';
|
18 |
-
*
|
19 |
-
* $sftp = new \phpseclib\Net\SFTP('www.domain.tld');
|
20 |
-
* if (!$sftp->login('username', 'password')) {
|
21 |
-
* exit('Login Failed');
|
22 |
-
* }
|
23 |
-
*
|
24 |
-
* echo $sftp->pwd() . "\r\n";
|
25 |
-
* $sftp->put('filename.ext', 'hello, world!');
|
26 |
-
* print_r($sftp->nlist());
|
27 |
-
* ?>
|
28 |
-
* </code>
|
29 |
-
*
|
30 |
-
* @category Net
|
31 |
-
* @package SFTP
|
32 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
33 |
-
* @copyright 2009 Jim Wigginton
|
34 |
-
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
35 |
-
* @link http://phpseclib.sourceforge.net
|
36 |
-
*/
|
37 |
-
|
38 |
-
namespace phpseclib\Net;
|
39 |
-
|
40 |
-
/**
|
41 |
-
* Pure-PHP implementations of SFTP.
|
42 |
-
*
|
43 |
-
* @package SFTP
|
44 |
-
* @author Jim Wigginton <terrafrost@php.net>
|
45 |
-
* @access public
|
46 |
-
*/
|
47 |
-
class SFTP extends SSH2
|
48 |
-
{
|
49 |
-
/**
|
50 |
-
* SFTP channel constant
|
51 |
-
*
|
52 |
-
* \phpseclib\Net\SSH2::exec() uses 0 and \phpseclib\Net\SSH2::read() / \phpseclib\Net\SSH2::write() use 1.
|
53 |
-
*
|
54 |
-
* @see \phpseclib\Net\SSH2::_send_channel_packet()
|
55 |
-
* @see \phpseclib\Net\SSH2::_get_channel_packet()
|
56 |
-
* @access private
|
57 |
-
*/
|
58 |
-
const CHANNEL = 0x100;
|
59 |
-
|
60 |
-
/**#@+
|
61 |
-
* @access public
|
62 |
-
* @see \phpseclib\Net\SFTP::put()
|
63 |
-
*/
|
64 |
-
/**
|
65 |
-
* Reads data from a local file.
|
66 |
-
*/
|
67 |
-
const SOURCE_LOCAL_FILE = 1;
|
68 |
-
/**
|
69 |
-
* Reads data from a string.
|
70 |
-
*/
|
71 |
-
// this value isn't really used anymore but i'm keeping it reserved for historical reasons
|
72 |
-
const SOURCE_STRING = 2;
|
73 |
-
/**
|
74 |
-
* Reads data from callback:
|
75 |
-
* function callback($length) returns string to proceed, null for EOF
|
76 |
-
*/
|
77 |
-
const SOURCE_CALLBACK = 16;
|
78 |
-
/**
|
79 |
-
* Resumes an upload
|
80 |
-
*/
|
81 |
-
const RESUME = 4;
|
82 |
-
/**
|
83 |
-
* Append a local file to an already existing remote file
|
84 |
-
*/
|
85 |
-
const RESUME_START = 8;
|
86 |
-
/**#@-*/
|
87 |
-
|
88 |
-
/**
|
89 |
-
* Packet Types
|
90 |
-
*
|
91 |
-
* @see self::__construct()
|
92 |
-
* @var array
|
93 |
-
* @access private
|
94 |
-
*/
|
95 |
-
var $packet_types = array();
|
96 |
-
|
97 |
-
/**
|
98 |
-
* Status Codes
|
99 |
-
*
|
100 |
-
* @see self::__construct()
|
101 |
-
* @var array
|
102 |
-
* @access private
|
103 |
-
*/
|
104 |
-
var $status_codes = array();
|
105 |
-
|
106 |
-
/**
|
107 |
-
* The Request ID
|
108 |
-
*
|
109 |
-
* The request ID exists in the off chance that a packet is sent out-of-order. Of course, this library doesn't support
|
110 |
-
* concurrent actions, so it's somewhat academic, here.
|
111 |
-
*
|
112 |
-
* @var int
|
113 |
-
* @see self::_send_sftp_packet()
|
114 |
-
* @access private
|
115 |
-
*/
|
116 |
-
var $request_id = false;
|
117 |
-
|
118 |
-
/**
|
119 |
-
* The Packet Type
|
120 |
-
*
|
121 |
-
* The request ID exists in the off chance that a packet is sent out-of-order. Of course, this library doesn't support
|
122 |
-
* concurrent actions, so it's somewhat academic, here.
|
123 |
-
*
|
124 |
-
* @var int
|
125 |
-
* @see self::_get_sftp_packet()
|
126 |
-
* @access private
|
127 |
-
*/
|
128 |
-
var $packet_type = -1;
|
129 |
-
|
130 |
-
/**
|
131 |
-
* Packet Buffer
|
132 |
-
*
|
133 |
-
* @var string
|
134 |
-
* @see self::_get_sftp_packet()
|
135 |
-
* @access private
|
136 |
-
*/
|
137 |
-
var $packet_buffer = '';
|
138 |
-
|
139 |
-
/**
|
140 |
-
* Extensions supported by the server
|
141 |
-
*
|
142 |
-
* @var array
|
143 |
-
* @see self::_initChannel()
|
144 |
-
* @access private
|
145 |
-
*/
|
146 |
-
var $extensions = array();
|
147 |
-
|
148 |
-
/**
|
149 |
-
* Server SFTP version
|
150 |
-
*
|
151 |
-
* @var int
|
152 |
-
* @see self::_initChannel()
|
153 |
-
* @access private
|
154 |
-
*/
|
155 |
-
var $version;
|
156 |
-
|
157 |
-
/**
|
158 |
-
* Current working directory
|
159 |
-
*
|
160 |
-
* @var string
|
161 |
-
* @see self::realpath()
|
162 |
-
* @see self::chdir()
|
163 |
-
* @access private
|
164 |
-
*/
|
165 |
-
var $pwd = false;
|
166 |
-
|
167 |
-
/**
|
168 |
-
* Packet Type Log
|
169 |
-
*
|
170 |
-
* @see self::getLog()
|
171 |
-
* @var array
|
172 |
-
* @access private
|
173 |
-
*/
|
174 |
-
var $packet_type_log = array();
|
175 |
-
|
176 |
-
/**
|
177 |
-
* Packet Log
|
178 |
-
*
|
179 |
-
* @see self::getLog()
|
180 |
-
* @var array
|
181 |
-
* @access private
|
182 |
-
*/
|
183 |
-
var $packet_log = array();
|
184 |
-
|
185 |
-
/**
|
186 |
-
* Error information
|
187 |
-
*
|
188 |
-
* @see self::getSFTPErrors()
|
189 |
-
* @see self::getLastSFTPError()
|
190 |
-
* @var array
|
191 |
-
* @access private
|
192 |
-
*/
|
193 |
-
var $sftp_errors = array();
|
194 |
-
|
195 |
-
/**
|
196 |
-
* Stat Cache
|
197 |
-
*
|
198 |
-
* Rather than always having to open a directory and close it immediately there after to see if a file is a directory
|
199 |
-
* we'll cache the results.
|
200 |
-
*
|
201 |
-
* @see self::_update_stat_cache()
|
202 |
-
* @see self::_remove_from_stat_cache()
|
203 |
-
* @see self::_query_stat_cache()
|
204 |
-
* @var array
|
205 |
-
* @access private
|
206 |
-
*/
|
207 |
-
var $stat_cache = array();
|
208 |
-
|
209 |
-
/**
|
210 |
-
* Max SFTP Packet Size
|
211 |
-
*
|
212 |
-
* @see self::__construct()
|
213 |
-
* @see self::get()
|
214 |
-
* @var array
|
215 |
-
* @access private
|
216 |
-
*/
|
217 |
-
var $max_sftp_packet;
|
218 |
-
|
219 |
-
/**
|
220 |
-
* Stat Cache Flag
|
221 |
-
*
|
222 |
-
* @see self::disableStatCache()
|
223 |
-
* @see self::enableStatCache()
|
224 |
-
* @var bool
|
225 |
-
* @access private
|
226 |
-
*/
|
227 |
-
var $use_stat_cache = true;
|
228 |
-
|
229 |
-
/**
|
230 |
-
* Sort Options
|
231 |
-
*
|
232 |
-
* @see self::_comparator()
|
233 |
-
* @see self::setListOrder()
|
234 |
-
* @var array
|
235 |
-
* @access private
|
236 |
-
*/
|
237 |
-
var $sortOptions = array();
|
238 |
-
|
239 |
-
/**
|
240 |
-
* Canonicalization Flag
|
241 |
-
*
|
242 |
-
* Determines whether or not paths should be canonicalized before being
|
243 |
-
* passed on to the remote server.
|
244 |
-
*
|
245 |
-
* @see self::enablePathCanonicalization()
|
246 |
-
* @see self::disablePathCanonicalization()
|
247 |
-
* @see self::realpath()
|
248 |
-
* @var bool
|
249 |
-
* @access private
|
250 |
-
*/
|
251 |
-
var $canonicalize_paths = true;
|
252 |
-
|
253 |
-
/**
|
254 |
-
* Default Constructor.
|
255 |
-
*
|
256 |
-
* Connects to an SFTP server
|
257 |
-
*
|
258 |
-
* @param string $host
|
259 |
-
* @param int $port
|
260 |
-
* @param int $timeout
|
261 |
-
* @return \phpseclib\Net\SFTP
|
262 |
-
* @access public
|
263 |
-
*/
|
264 |
-
function __construct($host, $port = 22, $timeout = 10)
|
265 |
-
{
|
266 |
-
parent::__construct($host, $port, $timeout);
|
267 |
-
|
268 |
-
$this->max_sftp_packet = 1 << 15;
|
269 |
-
|
270 |
-
$this->packet_types = array(
|
271 |
-
1 => 'NET_SFTP_INIT',
|
272 |
-
2 => 'NET_SFTP_VERSION',
|
273 |
-
/* the format of SSH_FXP_OPEN changed between SFTPv4 and SFTPv5+:
|
274 |
-
SFTPv5+: http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.1
|
275 |
-
pre-SFTPv5 : http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.3 */
|
276 |
-
3 => 'NET_SFTP_OPEN',
|
277 |
-
4 => 'NET_SFTP_CLOSE',
|
278 |
-
5 => 'NET_SFTP_READ',
|
279 |
-
6 => 'NET_SFTP_WRITE',
|
280 |
-
7 => 'NET_SFTP_LSTAT',
|
281 |
-
9 => 'NET_SFTP_SETSTAT',
|
282 |
-
11 => 'NET_SFTP_OPENDIR',
|
283 |
-
12 => 'NET_SFTP_READDIR',
|
284 |
-
13 => 'NET_SFTP_REMOVE',
|
285 |
-
14 => 'NET_SFTP_MKDIR',
|
286 |
-
15 => 'NET_SFTP_RMDIR',
|
287 |
-
16 => 'NET_SFTP_REALPATH',
|
288 |
-
17 => 'NET_SFTP_STAT',
|
289 |
-
/* the format of SSH_FXP_RENAME changed between SFTPv4 and SFTPv5+:
|
290 |
-
SFTPv5+: http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
|
291 |
-
pre-SFTPv5 : http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.5 */
|
292 |
-
18 => 'NET_SFTP_RENAME',
|
293 |
-
19 => 'NET_SFTP_READLINK',
|
294 |
-
20 => 'NET_SFTP_SYMLINK',
|
295 |
-
|
296 |
-
101=> 'NET_SFTP_STATUS',
|
297 |
-
102=> 'NET_SFTP_HANDLE',
|
298 |
-
/* the format of SSH_FXP_NAME changed between SFTPv3 and SFTPv4+:
|
299 |
-
SFTPv4+: http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.4
|
300 |
-
pre-SFTPv4 : http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-7 */
|
301 |
-
103=> 'NET_SFTP_DATA',
|
302 |
-
104=> 'NET_SFTP_NAME',
|
303 |
-
105=> 'NET_SFTP_ATTRS',
|
304 |
-
|
305 |
-
200=> 'NET_SFTP_EXTENDED'
|
306 |
-
);
|
307 |
-
$this->status_codes = array(
|
308 |
-
0 => 'NET_SFTP_STATUS_OK',
|
309 |
-
1 => 'NET_SFTP_STATUS_EOF',
|
310 |
-
2 => 'NET_SFTP_STATUS_NO_SUCH_FILE',
|
311 |
-
3 => 'NET_SFTP_STATUS_PERMISSION_DENIED',
|
312 |
-
4 => 'NET_SFTP_STATUS_FAILURE',
|
313 |
-
5 => 'NET_SFTP_STATUS_BAD_MESSAGE',
|
314 |
-
6 => 'NET_SFTP_STATUS_NO_CONNECTION',
|
315 |
-
7 => 'NET_SFTP_STATUS_CONNECTION_LOST',
|
316 |
-
8 => 'NET_SFTP_STATUS_OP_UNSUPPORTED',
|
317 |
-
9 => 'NET_SFTP_STATUS_INVALID_HANDLE',
|
318 |
-
10 => 'NET_SFTP_STATUS_NO_SUCH_PATH',
|
319 |
-
11 => 'NET_SFTP_STATUS_FILE_ALREADY_EXISTS',
|
320 |
-
12 => 'NET_SFTP_STATUS_WRITE_PROTECT',
|
321 |
-
13 => 'NET_SFTP_STATUS_NO_MEDIA',
|
322 |
-
14 => 'NET_SFTP_STATUS_NO_SPACE_ON_FILESYSTEM',
|
323 |
-
15 => 'NET_SFTP_STATUS_QUOTA_EXCEEDED',
|
324 |
-
16 => 'NET_SFTP_STATUS_UNKNOWN_PRINCIPAL',
|
325 |
-
17 => 'NET_SFTP_STATUS_LOCK_CONFLICT',
|
326 |
-
18 => 'NET_SFTP_STATUS_DIR_NOT_EMPTY',
|
327 |
-
19 => 'NET_SFTP_STATUS_NOT_A_DIRECTORY',
|
328 |
-
20 => 'NET_SFTP_STATUS_INVALID_FILENAME',
|
329 |
-
21 => 'NET_SFTP_STATUS_LINK_LOOP',
|
330 |
-
22 => 'NET_SFTP_STATUS_CANNOT_DELETE',
|
331 |
-
23 => 'NET_SFTP_STATUS_INVALID_PARAMETER',
|
332 |
-
24 => 'NET_SFTP_STATUS_FILE_IS_A_DIRECTORY',
|
333 |
-
25 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_CONFLICT',
|
334 |
-
26 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_REFUSED',
|
335 |
-
27 => 'NET_SFTP_STATUS_DELETE_PENDING',
|
336 |
-
28 => 'NET_SFTP_STATUS_FILE_CORRUPT',
|
337 |
-
29 => 'NET_SFTP_STATUS_OWNER_INVALID',
|
338 |
-
30 => 'NET_SFTP_STATUS_GROUP_INVALID',
|
339 |
-
31 => 'NET_SFTP_STATUS_NO_MATCHING_BYTE_RANGE_LOCK'
|
340 |
-
);
|
341 |
-
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-7.1
|
342 |
-
// the order, in this case, matters quite a lot - see \phpseclib\Net\SFTP::_parseAttributes() to understand why
|
343 |
-
$this->attributes = array(
|
344 |
-
0x00000001 => 'NET_SFTP_ATTR_SIZE',
|
345 |
-
0x00000002 => 'NET_SFTP_ATTR_UIDGID', // defined in SFTPv3, removed in SFTPv4+
|
346 |
-
0x00000004 => 'NET_SFTP_ATTR_PERMISSIONS',
|
347 |
-
0x00000008 => 'NET_SFTP_ATTR_ACCESSTIME',
|
348 |
-
// 0x80000000 will yield a floating point on 32-bit systems and converting floating points to integers
|
349 |
-
// yields inconsistent behavior depending on how php is compiled. so we left shift -1 (which, in
|
350 |
-
// two's compliment, consists of all 1 bits) by 31. on 64-bit systems this'll yield 0xFFFFFFFF80000000.
|
351 |
-
// that's not a problem, however, and 'anded' and a 32-bit number, as all the leading 1 bits are ignored.
|
352 |
-
-1 << 31 => 'NET_SFTP_ATTR_EXTENDED'
|
353 |
-
);
|
354 |
-
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.3
|
355 |
-
// the flag definitions change somewhat in SFTPv5+. if SFTPv5+ support is added to this library, maybe name
|
356 |
-
// the array for that $this->open5_flags and similarly alter the constant names.
|
357 |
-
$this->open_flags = array(
|
358 |
-
0x00000001 => 'NET_SFTP_OPEN_READ',
|
359 |
-
0x00000002 => 'NET_SFTP_OPEN_WRITE',
|
360 |
-
0x00000004 => 'NET_SFTP_OPEN_APPEND',
|
361 |
-
0x00000008 => 'NET_SFTP_OPEN_CREATE',
|
362 |
-
0x00000010 => 'NET_SFTP_OPEN_TRUNCATE',
|
363 |
-
0x00000020 => 'NET_SFTP_OPEN_EXCL'
|
364 |
-
);
|
365 |
-
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-5.2
|
366 |
-
// see \phpseclib\Net\SFTP::_parseLongname() for an explanation
|
367 |
-
$this->file_types = array(
|
368 |
-
1 => 'NET_SFTP_TYPE_REGULAR',
|
369 |
-
2 => 'NET_SFTP_TYPE_DIRECTORY',
|
370 |
-
3 => 'NET_SFTP_TYPE_SYMLINK',
|
371 |
-
4 => 'NET_SFTP_TYPE_SPECIAL',
|
372 |
-
5 => 'NET_SFTP_TYPE_UNKNOWN',
|
373 |
-
// the followin types were first defined for use in SFTPv5+
|
374 |
-
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-05#section-5.2
|
375 |
-
6 => 'NET_SFTP_TYPE_SOCKET',
|
376 |
-
7 => 'NET_SFTP_TYPE_CHAR_DEVICE',
|
377 |
-
8 => 'NET_SFTP_TYPE_BLOCK_DEVICE',
|
378 |
-
9 => 'NET_SFTP_TYPE_FIFO'
|
379 |
-
);
|
380 |
-
$this->_define_array(
|
381 |
-
$this->packet_types,
|
382 |
-
$this->status_codes,
|
383 |
-
$this->attributes,
|
384 |
-
$this->open_flags,
|
385 |
-
$this->file_types
|
386 |
-
);
|
387 |
-
|
388 |
-
if (!defined('NET_SFTP_QUEUE_SIZE')) {
|
389 |
-
define('NET_SFTP_QUEUE_SIZE', 32);
|
390 |
-
}
|
391 |
-
}
|
392 |
-
|
393 |
-
/**
|
394 |
-
* Login
|
395 |
-
*
|
396 |
-
* @param string $username
|
397 |
-
* @param string $password
|
398 |
-
* @return bool
|
399 |
-
* @access public
|
400 |
-
*/
|
401 |
-
function login($username)
|
402 |
-
{
|
403 |
-
$args = func_get_args();
|
404 |
-
if (!call_user_func_array(array(&$this, '_login'), $args)) {
|
405 |
-
return false;
|
406 |
-
}
|
407 |
-
|
408 |
-
$this->window_size_server_to_client[self::CHANNEL] = $this->window_size;
|
409 |
-
|
410 |
-
$packet = pack(
|
411 |
-
'CNa*N3',
|
412 |
-
NET_SSH2_MSG_CHANNEL_OPEN,
|
413 |
-
strlen('session'),
|
414 |
-
'session',
|
415 |
-
self::CHANNEL,
|
416 |
-
$this->window_size,
|
417 |
-
0x4000
|
418 |
-
);
|
419 |
-
|
420 |
-
if (!$this->_send_binary_packet($packet)) {
|
421 |
-
return false;
|
422 |
-
}
|
423 |
-
|
424 |
-
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_OPEN;
|
425 |
-
|
426 |
-
$response = $this->_get_channel_packet(self::CHANNEL, true);
|
427 |
-
if ($response === false) {
|
428 |
-
return false;
|
429 |
-
}
|
430 |
-
|
431 |
-
$packet = pack(
|
432 |
-
'CNNa*CNa*',
|
433 |
-
NET_SSH2_MSG_CHANNEL_REQUEST,
|
434 |
-
$this->server_channels[self::CHANNEL],
|
435 |
-
strlen('subsystem'),
|
436 |
-
'subsystem',
|
437 |
-
1,
|
438 |
-
strlen('sftp'),
|
439 |
-
'sftp'
|
440 |
-
);
|
441 |
-
if (!$this->_send_binary_packet($packet)) {
|
442 |
-
return false;
|
443 |
-
}
|
444 |
-
|
445 |
-
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
|
446 |
-
|
447 |
-
$response = $this->_get_channel_packet(self::CHANNEL, true);
|
448 |
-
if ($response === false) {
|
449 |
-
// from PuTTY's psftp.exe
|
450 |
-
$command = "test -x /usr/lib/sftp-server && exec /usr/lib/sftp-server\n" .
|
451 |
-
"test -x /usr/local/lib/sftp-server && exec /usr/local/lib/sftp-server\n" .
|
452 |
-
"exec sftp-server";
|
453 |
-
// we don't do $this->exec($command, false) because exec() operates on a different channel and plus the SSH_MSG_CHANNEL_OPEN that exec() does
|
454 |
-
// is redundant
|
455 |
-
$packet = pack(
|
456 |
-
'CNNa*CNa*',
|
457 |
-
NET_SSH2_MSG_CHANNEL_REQUEST,
|
458 |
-
$this->server_channels[self::CHANNEL],
|
459 |
-
strlen('exec'),
|
460 |
-
'exec',
|
461 |
-
1,
|
462 |
-
strlen($command),
|
463 |
-
$command
|
464 |
-
);
|
465 |
-
if (!$this->_send_binary_packet($packet)) {
|
466 |
-
return false;
|
467 |
-
}
|
468 |
-
|
469 |
-
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
|
470 |
-
|
471 |
-
$response = $this->_get_channel_packet(self::CHANNEL, true);
|
472 |
-
if ($response === false) {
|
473 |
-
return false;
|
474 |
-
}
|
475 |
-
}
|
476 |
-
|
477 |
-
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_DATA;
|
478 |
-
|
479 |
-
if (!$this->_send_sftp_packet(NET_SFTP_INIT, "\0\0\0\3")) {
|
480 |
-
return false;
|
481 |
-
}
|
482 |
-
|
483 |
-
$response = $this->_get_sftp_packet();
|
484 |
-
if ($this->packet_type != NET_SFTP_VERSION) {
|
485 |
-
user_error('Expected SSH_FXP_VERSION');
|
486 |
-
return false;
|
487 |
-
}
|
488 |
-
|
489 |
-
if (strlen($response) < 4) {
|
490 |
-
return false;
|
491 |
-
}
|
492 |
-
extract(unpack('Nversion', $this->_string_shift($response, 4)));
|
493 |
-
$this->version = $version;
|
494 |
-
while (!empty($response)) {
|
495 |
-
if (strlen($response) < 4) {
|
496 |
-
return false;
|
497 |
-
}
|
498 |
-
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
499 |
-
$key = $this->_string_shift($response, $length);
|
500 |
-
if (strlen($response) < 4) {
|
501 |
-
return false;
|
502 |
-
}
|
503 |
-
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
504 |
-
$value = $this->_string_shift($response, $length);
|
505 |
-
$this->extensions[$key] = $value;
|
506 |
-
}
|
507 |
-
|
508 |
-
/*
|
509 |
-
SFTPv4+ defines a 'newline' extension. SFTPv3 seems to have unofficial support for it via 'newline@vandyke.com',
|
510 |
-
however, I'm not sure what 'newline@vandyke.com' is supposed to do (the fact that it's unofficial means that it's
|
511 |
-
not in the official SFTPv3 specs) and 'newline@vandyke.com' / 'newline' are likely not drop-in substitutes for
|
512 |
-
one another due to the fact that 'newline' comes with a SSH_FXF_TEXT bitmask whereas it seems unlikely that
|
513 |
-
'newline@vandyke.com' would.
|
514 |
-
*/
|
515 |
-
/*
|
516 |
-
if (isset($this->extensions['newline@vandyke.com'])) {
|
517 |
-
$this->extensions['newline'] = $this->extensions['newline@vandyke.com'];
|
518 |
-
unset($this->extensions['newline@vandyke.com']);
|
519 |
-
}
|
520 |
-
*/
|
521 |
-
|
522 |
-
$this->request_id = 1;
|
523 |
-
|
524 |
-
/*
|
525 |
-
A Note on SFTPv4/5/6 support:
|
526 |
-
<http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-5.1> states the following:
|
527 |
-
|
528 |
-
"If the client wishes to interoperate with servers that support noncontiguous version
|
529 |
-
numbers it SHOULD send '3'"
|
530 |
-
|
531 |
-
Given that the server only sends its version number after the client has already done so, the above
|
532 |
-
seems to be suggesting that v3 should be the default version. This makes sense given that v3 is the
|
533 |
-
most popular.
|
534 |
-
|
535 |
-
<http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-5.5> states the following;
|
536 |
-
|
537 |
-
"If the server did not send the "versions" extension, or the version-from-list was not included, the
|
538 |
-
server MAY send a status response describing the failure, but MUST then close the channel without
|
539 |
-
processing any further requests."
|
540 |
-
|
541 |
-
So what do you do if you have a client whose initial SSH_FXP_INIT packet says it implements v3 and
|
542 |
-
a server whose initial SSH_FXP_VERSION reply says it implements v4 and only v4? If it only implements
|
543 |
-
v4, the "versions" extension is likely not going to have been sent so version re-negotiation as discussed
|
544 |
-
in draft-ietf-secsh-filexfer-13 would be quite impossible. As such, what \phpseclib\Net\SFTP would do is close the
|
545 |
-
channel and reopen it with a new and updated SSH_FXP_INIT packet.
|
546 |
-
*/
|
547 |
-
switch ($this->version) {
|
548 |
-
case 2:
|
549 |
-
case 3:
|
550 |
-
break;
|
551 |
-
default:
|
552 |
-
return false;
|
553 |
-
}
|
554 |
-
|
555 |
-
$this->pwd = $this->_realpath('.');
|
556 |
-
|
557 |
-
$this->_update_stat_cache($this->pwd, array());
|
558 |
-
|
559 |
-
return true;
|
560 |
-
}
|
561 |
-
|
562 |
-
/**
|
563 |
-
* Disable the stat cache
|
564 |
-
*
|
565 |
-
* @access public
|
566 |
-
*/
|
567 |
-
function disableStatCache()
|
568 |
-
{
|
569 |
-
$this->use_stat_cache = false;
|
570 |
-
}
|
571 |
-
|
572 |
-
/**
|
573 |
-
* Enable the stat cache
|
574 |
-
*
|
575 |
-
* @access public
|
576 |
-
*/
|
577 |
-
function enableStatCache()
|
578 |
-
{
|
579 |
-
$this->use_stat_cache = true;
|
580 |
-
}
|
581 |
-
|
582 |
-
/**
|
583 |
-
* Clear the stat cache
|
584 |
-
*
|
585 |
-
* @access public
|
586 |
-
*/
|
587 |
-
function clearStatCache()
|
588 |
-
{
|
589 |
-
$this->stat_cache = array();
|
590 |
-
}
|
591 |
-
|
592 |
-
/**
|
593 |
-
* Enable path canonicalization
|
594 |
-
*
|
595 |
-
* @access public
|
596 |
-
*/
|
597 |
-
function enablePathCanonicalization()
|
598 |
-
{
|
599 |
-
$this->canonicalize_paths = true;
|
600 |
-
}
|
601 |
-
|
602 |
-
/**
|
603 |
-
* Enable path canonicalization
|
604 |
-
*
|
605 |
-
* @access public
|
606 |
-
*/
|
607 |
-
function disablePathCanonicalization()
|
608 |
-
{
|
609 |
-
$this->canonicalize_paths = false;
|
610 |
-
}
|
611 |
-
|
612 |
-
/**
|
613 |
-
* Returns the current directory name
|
614 |
-
*
|
615 |
-
* @return mixed
|
616 |
-
* @access public
|
617 |
-
*/
|
618 |
-
function pwd()
|
619 |
-
{
|
620 |
-
return $this->pwd;
|
621 |
-
}
|
622 |
-
|
623 |
-
/**
|
624 |
-
* Logs errors
|
625 |
-
*
|
626 |
-
* @param string $response
|
627 |
-
* @param int $status
|
628 |
-
* @access public
|
629 |
-
*/
|
630 |
-
function _logError($response, $status = -1)
|
631 |
-
{
|
632 |
-
if ($status == -1) {
|
633 |
-
if (strlen($response) < 4) {
|
634 |
-
return;
|
635 |
-
}
|
636 |
-
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
637 |
-
}
|
638 |
-
|
639 |
-
$error = $this->status_codes[$status];
|
640 |
-
|
641 |
-
if ($this->version > 2 || strlen($response) < 4) {
|
642 |
-
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
643 |
-
$this->sftp_errors[] = $error . ': ' . $this->_string_shift($response, $length);
|
644 |
-
} else {
|
645 |
-
$this->sftp_errors[] = $error;
|
646 |
-
}
|
647 |
-
}
|
648 |
-
|
649 |
-
/**
|
650 |
-
* Returns canonicalized absolute pathname
|
651 |
-
*
|
652 |
-
* realpath() expands all symbolic links and resolves references to '/./', '/../' and extra '/' characters in the input
|
653 |
-
* path and returns the canonicalized absolute pathname.
|
654 |
-
*
|
655 |
-
* @param string $path
|
656 |
-
* @return mixed
|
657 |
-
* @access public
|
658 |
-
*/
|
659 |
-
function realpath($path)
|
660 |
-
{
|
661 |
-
return $this->_realpath($path);
|
662 |
-
}
|
663 |
-
|
664 |
-
/**
|
665 |
-
* Canonicalize the Server-Side Path Name
|
666 |
-
*
|
667 |
-
* SFTP doesn't provide a mechanism by which the current working directory can be changed, so we'll emulate it. Returns
|
668 |
-
* the absolute (canonicalized) path.
|
669 |
-
*
|
670 |
-
* If canonicalize_paths has been disabled using disablePathCanonicalization(), $path is returned as-is.
|
671 |
-
*
|
672 |
-
* @see self::chdir()
|
673 |
-
* @see self::disablePathCanonicalization()
|
674 |
-
* @param string $path
|
675 |
-
* @return mixed
|
676 |
-
* @access private
|
677 |
-
*/
|
678 |
-
function _realpath($path)
|
679 |
-
{
|
680 |
-
if (!$this->canonicalize_paths) {
|
681 |
-
return $path;
|
682 |
-
}
|
683 |
-
|
684 |
-
if ($this->pwd === false) {
|
685 |
-
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.9
|
686 |
-
if (!$this->_send_sftp_packet(NET_SFTP_REALPATH, pack('Na*', strlen($path), $path))) {
|
687 |
-
return false;
|
688 |
-
}
|
689 |
-
|
690 |
-
$response = $this->_get_sftp_packet();
|
691 |
-
switch ($this->packet_type) {
|
692 |
-
case NET_SFTP_NAME:
|
693 |
-
// although SSH_FXP_NAME is implemented differently in SFTPv3 than it is in SFTPv4+, the following
|
694 |
-
// should work on all SFTP versions since the only part of the SSH_FXP_NAME packet the following looks
|
695 |
-
// at is the first part and that part is defined the same in SFTP versions 3 through 6.
|
696 |
-
$this->_string_shift($response, 4); // skip over the count - it should be 1, anyway
|
697 |
-
if (strlen($response) < 4) {
|
698 |
-
return false;
|
699 |
-
}
|
700 |
-
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
701 |
-
return $this->_string_shift($response, $length);
|
702 |
-
case NET_SFTP_STATUS:
|
703 |
-
$this->_logError($response);
|
704 |
-
return false;
|
705 |
-
default:
|
706 |
-
user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
|
707 |
-
return false;
|
708 |
-
}
|
709 |
-
}
|
710 |
-
|
711 |
-
if ($path[0] != '/') {
|
712 |
-
$path = $this->pwd . '/' . $path;
|
713 |
-
}
|
714 |
-
|
715 |
-
$path = explode('/', $path);
|
716 |
-
$new = array();
|
717 |
-
foreach ($path as $dir) {
|
718 |
-
if (!strlen($dir)) {
|
719 |
-
continue;
|
720 |
-
}
|
721 |
-
switch ($dir) {
|
722 |
-
case '..':
|
723 |
-
array_pop($new);
|
724 |
-
case '.':
|
725 |
-
break;
|
726 |
-
default:
|
727 |
-
$new[] = $dir;
|
728 |
-
}
|
729 |
-
}
|
730 |
-
|
731 |
-
return '/' . implode('/', $new);
|
732 |
-
}
|
733 |
-
|
734 |
-
/**
|
735 |
-
* Changes the current directory
|
736 |
-
*
|
737 |
-
* @param string $dir
|
738 |
-
* @return bool
|
739 |
-
* @access public
|
740 |
-
*/
|
741 |
-
function chdir($dir)
|
742 |
-
{
|
743 |
-
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
|
744 |
-
return false;
|
745 |
-
}
|
746 |
-
|
747 |
-
// assume current dir if $dir is empty
|
748 |
-
if ($dir === '') {
|
749 |
-
$dir = './';
|
750 |
-
// suffix a slash if needed
|
751 |
-
} elseif ($dir[strlen($dir) - 1] != '/') {
|
752 |
-
$dir.= '/';
|
753 |
-
}
|
754 |
-
|
755 |
-
$dir = $this->_realpath($dir);
|
756 |
-
|
757 |
-
// confirm that $dir is, in fact, a valid directory
|
758 |
-
if ($this->use_stat_cache && is_array($this->_query_stat_cache($dir))) {
|
759 |
-
$this->pwd = $dir;
|
760 |
-
return true;
|
761 |
-
}
|
762 |
-
|
763 |
-
// we could do a stat on the alleged $dir to see if it's a directory but that doesn't tell us
|
764 |
-
// the currently logged in user has the appropriate permissions or not. maybe you could see if
|
765 |
-
// the file's uid / gid match the currently logged in user's uid / gid but how there's no easy
|
766 |
-
// way to get those with SFTP
|
767 |
-
|
768 |
-
if (!$this->_send_sftp_packet(NET_SFTP_OPENDIR, pack('Na*', strlen($dir), $dir))) {
|
769 |
-
return false;
|
770 |
-
}
|
771 |
-
|
772 |
-
// see \phpseclib\Net\SFTP::nlist() for a more thorough explanation of the following
|
773 |
-
$response = $this->_get_sftp_packet();
|
774 |
-
switch ($this->packet_type) {
|
775 |
-
case NET_SFTP_HANDLE:
|
776 |
-
$handle = substr($response, 4);
|
777 |
-
break;
|
778 |
-
case NET_SFTP_STATUS:
|
779 |
-
$this->_logError($response);
|
780 |
-
return false;
|
781 |
-
default:
|
782 |
-
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
783 |
-
return false;
|
784 |
-
}
|
785 |
-
|
786 |
-
if (!$this->_close_handle($handle)) {
|
787 |
-
return false;
|
788 |
-
}
|
789 |
-
|
790 |
-
$this->_update_stat_cache($dir, array());
|
791 |
-
|
792 |
-
$this->pwd = $dir;
|
793 |
-
return true;
|
794 |
-
}
|
795 |
-
|
796 |
-
/**
|
797 |
-
* Returns a list of files in the given directory
|
798 |
-
*
|
799 |
-
* @param string $dir
|
800 |
-
* @param bool $recursive
|
801 |
-
* @return mixed
|
802 |
-
* @access public
|
803 |
-
*/
|
804 |
-
function nlist($dir = '.', $recursive = false)
|
805 |
-
{
|
806 |
-
return $this->_nlist_helper($dir, $recursive, '');
|
807 |
-
}
|
808 |
-
|
809 |
-
/**
|
810 |
-
* Helper method for nlist
|
811 |
-
*
|
812 |
-
* @param string $dir
|
813 |
-
* @param bool $recursive
|
814 |
-
* @param string $relativeDir
|
815 |
-
* @return mixed
|
816 |
-
* @access private
|
817 |
-
*/
|
818 |
-
function _nlist_helper($dir, $recursive, $relativeDir)
|
819 |
-
{
|
820 |
-
$files = $this->_list($dir, false);
|
821 |
-
|
822 |
-
if (!$recursive || $files === false) {
|
823 |
-
return $files;
|
824 |
-
}
|
825 |
-
|
826 |
-
$result = array();
|
827 |
-
foreach ($files as $value) {
|
828 |
-
if ($value == '.' || $value == '..') {
|
829 |
-
if ($relativeDir == '') {
|
830 |
-
$result[] = $value;
|
831 |
-
}
|
832 |
-
continue;
|
833 |
-
}
|
834 |
-
if (is_array($this->_query_stat_cache($this->_realpath($dir . '/' . $value)))) {
|
835 |
-
$temp = $this->_nlist_helper($dir . '/' . $value, true, $relativeDir . $value . '/');
|
836 |
-
$result = array_merge($result, $temp);
|
837 |
-
} else {
|
838 |
-
$result[] = $relativeDir . $value;
|
839 |
-
}
|
840 |
-
}
|
841 |
-
|
842 |
-
return $result;
|
843 |
-
}
|
844 |
-
|
845 |
-
/**
|
846 |
-
* Returns a detailed list of files in the given directory
|
847 |
-
*
|
848 |
-
* @param string $dir
|
849 |
-
* @param bool $recursive
|
850 |
-
* @return mixed
|
851 |
-
* @access public
|
852 |
-
*/
|
853 |
-
function rawlist($dir = '.', $recursive = false)
|
854 |
-
{
|
855 |
-
$files = $this->_list($dir, true);
|
856 |
-
if (!$recursive || $files === false) {
|
857 |
-
return $files;
|
858 |
-
}
|
859 |
-
|
860 |
-
static $depth = 0;
|
861 |
-
|
862 |
-
foreach ($files as $key => $value) {
|
863 |
-
if ($depth != 0 && $key == '..') {
|
864 |
-
unset($files[$key]);
|
865 |
-
continue;
|
866 |
-
}
|
867 |
-
if ($key != '.' && $key != '..' && is_array($this->_query_stat_cache($this->_realpath($dir . '/' . $key)))) {
|
868 |
-
$depth++;
|
869 |
-
$files[$key] = $this->rawlist($dir . '/' . $key, true);
|
870 |
-
$depth--;
|
871 |
-
} else {
|
872 |
-
$files[$key] = (object) $value;
|
873 |
-
}
|
874 |
-
}
|
875 |
-
|
876 |
-
return $files;
|
877 |
-
}
|
878 |
-
|
879 |
-
/**
|
880 |
-
* Reads a list, be it detailed or not, of files in the given directory
|
881 |
-
*
|
882 |
-
* @param string $dir
|
883 |
-
* @param bool $raw
|
884 |
-
* @return mixed
|
885 |
-
* @access private
|
886 |
-
*/
|
887 |
-
function _list($dir, $raw = true)
|
888 |
-
{
|
889 |
-
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
|
890 |
-
return false;
|
891 |
-
}
|
892 |
-
|
893 |
-
$dir = $this->_realpath($dir . '/');
|
894 |
-
if ($dir === false) {
|
895 |
-
return false;
|
896 |
-
}
|
897 |
-
|
898 |
-
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.2
|
899 |
-
if (!$this->_send_sftp_packet(NET_SFTP_OPENDIR, pack('Na*', strlen($dir), $dir))) {
|
900 |
-
return false;
|
901 |
-
}
|
902 |
-
|
903 |
-
$response = $this->_get_sftp_packet();
|
904 |
-
switch ($this->packet_type) {
|
905 |
-
case NET_SFTP_HANDLE:
|
906 |
-
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.2
|
907 |
-
// since 'handle' is the last field in the SSH_FXP_HANDLE packet, we'll just remove the first four bytes that
|
908 |
-
// represent the length of the string and leave it at that
|
909 |
-
$handle = substr($response, 4);
|
910 |
-
break;
|
911 |
-
case NET_SFTP_STATUS:
|
912 |
-
// presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
|
913 |
-
$this->_logError($response);
|
914 |
-
return false;
|
915 |
-
default:
|
916 |
-
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
917 |
-
return false;
|
918 |
-
}
|
919 |
-
|
920 |
-
$this->_update_stat_cache($dir, array());
|
921 |
-
|
922 |
-
$contents = array();
|
923 |
-
while (true) {
|
924 |
-
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.2
|
925 |
-
// why multiple SSH_FXP_READDIR packets would be sent when the response to a single one can span arbitrarily many
|
926 |
-
// SSH_MSG_CHANNEL_DATA messages is not known to me.
|
927 |
-
if (!$this->_send_sftp_packet(NET_SFTP_READDIR, pack('Na*', strlen($handle), $handle))) {
|
928 |
-
return false;
|
929 |
-
}
|
930 |
-
|
931 |
-
$response = $this->_get_sftp_packet();
|
932 |
-
switch ($this->packet_type) {
|
933 |
-
case NET_SFTP_NAME:
|
934 |
-
if (strlen($response) < 4) {
|
935 |
-
return false;
|
936 |
-
}
|
937 |
-
extract(unpack('Ncount', $this->_string_shift($response, 4)));
|
938 |
-
for ($i = 0; $i < $count; $i++) {
|
939 |
-
if (strlen($response) < 4) {
|
940 |
-
return false;
|
941 |
-
}
|
942 |
-
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
943 |
-
$shortname = $this->_string_shift($response, $length);
|
944 |
-
if (strlen($response) < 4) {
|
945 |
-
return false;
|
946 |
-
}
|
947 |
-
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
948 |
-
$longname = $this->_string_shift($response, $length);
|
949 |
-
$attributes = $this->_parseAttributes($response);
|
950 |
-
if (!isset($attributes['type'])) {
|
951 |
-
$fileType = $this->_parseLongname($longname);
|
952 |
-
if ($fileType) {
|
953 |
-
$attributes['type'] = $fileType;
|
954 |
-
}
|
955 |
-
}
|
956 |
-
$contents[$shortname] = $attributes + array('filename' => $shortname);
|
957 |
-
|
958 |
-
if (isset($attributes['type']) && $attributes['type'] == NET_SFTP_TYPE_DIRECTORY && ($shortname != '.' && $shortname != '..')) {
|
959 |
-
$this->_update_stat_cache($dir . '/' . $shortname, array());
|
960 |
-
} else {
|
961 |
-
if ($shortname == '..') {
|
962 |
-
$temp = $this->_realpath($dir . '/..') . '/.';
|
963 |
-
} else {
|
964 |
-
$temp = $dir . '/' . $shortname;
|
965 |
-
}
|
966 |
-
$this->_update_stat_cache($temp, (object) array('lstat' => $attributes));
|
967 |
-
}
|
968 |
-
// SFTPv6 has an optional boolean end-of-list field, but we'll ignore that, since the
|
969 |
-
// final SSH_FXP_STATUS packet should tell us that, already.
|
970 |
-
}
|
971 |
-
break;
|
972 |
-
case NET_SFTP_STATUS:
|
973 |
-
if (strlen($response) < 4) {
|
974 |
-
return false;
|
975 |
-
}
|
976 |
-
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
977 |
-
if ($status != NET_SFTP_STATUS_EOF) {
|
978 |
-
$this->_logError($response, $status);
|
979 |
-
return false;
|
980 |
-
}
|
981 |
-
break 2;
|
982 |
-
default:
|
983 |
-
user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
|
984 |
-
return false;
|
985 |
-
}
|
986 |
-
}
|
987 |
-
|
988 |
-
if (!$this->_close_handle($handle)) {
|
989 |
-
return false;
|
990 |
-
}
|
991 |
-
|
992 |
-
if (count($this->sortOptions)) {
|
993 |
-
uasort($contents, array(&$this, '_comparator'));
|
994 |
-
}
|
995 |
-
|
996 |
-
return $raw ? $contents : array_keys($contents);
|
997 |
-
}
|
998 |
-
|
999 |
-
/**
|
1000 |
-
* Compares two rawlist entries using parameters set by setListOrder()
|
1001 |
-
*
|
1002 |
-
* Intended for use with uasort()
|
1003 |
-
*
|
1004 |
-
* @param array $a
|
1005 |
-
* @param array $b
|
1006 |
-
* @return int
|
1007 |
-
* @access private
|
1008 |
-
*/
|
1009 |
-
function _comparator($a, $b)
|
1010 |
-
{
|
1011 |
-
switch (true) {
|
1012 |
-
case $a['filename'] === '.' || $b['filename'] === '.':
|
1013 |
-
if ($a['filename'] === $b['filename']) {
|
1014 |
-
return 0;
|
1015 |
-
}
|
1016 |
-
return $a['filename'] === '.' ? -1 : 1;
|
1017 |
-
case $a['filename'] === '..' || $b['filename'] === '..':
|
1018 |
-
if ($a['filename'] === $b['filename']) {
|
1019 |
-
return 0;
|
1020 |
-
}
|
1021 |
-
return $a['filename'] === '..' ? -1 : 1;
|
1022 |
-
case isset($a['type']) && $a['type'] === NET_SFTP_TYPE_DIRECTORY:
|
1023 |
-
if (!isset($b['type'])) {
|
1024 |
-
return 1;
|
1025 |
-
}
|
1026 |
-
if ($b['type'] !== $a['type']) {
|
1027 |
-
return -1;
|
1028 |
-
}
|
1029 |
-
break;
|
1030 |
-
case isset($b['type']) && $b['type'] === NET_SFTP_TYPE_DIRECTORY:
|
1031 |
-
return 1;
|
1032 |
-
}
|
1033 |
-
foreach ($this->sortOptions as $sort => $order) {
|
1034 |
-
if (!isset($a[$sort]) || !isset($b[$sort])) {
|
1035 |
-
if (isset($a[$sort])) {
|
1036 |
-
return -1;
|
1037 |
-
}
|
1038 |
-
if (isset($b[$sort])) {
|
1039 |
-
return 1;
|
1040 |
-
}
|
1041 |
-
return 0;
|
1042 |
-
}
|
1043 |
-
switch ($sort) {
|
1044 |
-
case 'filename':
|
1045 |
-
$result = strcasecmp($a['filename'], $b['filename']);
|
1046 |
-
if ($result) {
|
1047 |
-
return $order === SORT_DESC ? -$result : $result;
|
1048 |
-
}
|
1049 |
-
break;
|
1050 |
-
case 'permissions':
|
1051 |
-
case 'mode':
|
1052 |
-
$a[$sort]&= 07777;
|
1053 |
-
$b[$sort]&= 07777;
|
1054 |
-
default:
|
1055 |
-
if ($a[$sort] === $b[$sort]) {
|
1056 |
-
break;
|
1057 |
-
}
|
1058 |
-
return $order === SORT_ASC ? $a[$sort] - $b[$sort] : $b[$sort] - $a[$sort];
|
1059 |
-
}
|
1060 |
-
}
|
1061 |
-
}
|
1062 |
-
|
1063 |
-
/**
|
1064 |
-
* Defines how nlist() and rawlist() will be sorted - if at all.
|
1065 |
-
*
|
1066 |
-
* If sorting is enabled directories and files will be sorted independently with
|
1067 |
-
* directories appearing before files in the resultant array that is returned.
|
1068 |
-
*
|
1069 |
-
* Any parameter returned by stat is a valid sort parameter for this function.
|
1070 |
-
* Filename comparisons are case insensitive.
|
1071 |
-
*
|
1072 |
-
* Examples:
|
1073 |
-
*
|
1074 |
-
* $sftp->setListOrder('filename', SORT_ASC);
|
1075 |
-
* $sftp->setListOrder('size', SORT_DESC, 'filename', SORT_ASC);
|
1076 |
-
* $sftp->setListOrder(true);
|
1077 |
-
* Separates directories from files but doesn't do any sorting beyond that
|
1078 |
-
* $sftp->setListOrder();
|
1079 |
-
* Don't do any sort of sorting
|
1080 |
-
*
|
1081 |
-
* @access public
|
1082 |
-
*/
|
1083 |
-
function setListOrder()
|
1084 |
-
{
|
1085 |
-
$this->sortOptions = array();
|
1086 |
-
$args = func_get_args();
|
1087 |
-
if (empty($args)) {
|
1088 |
-
return;
|
1089 |
-
}
|
1090 |
-
$len = count($args) & 0x7FFFFFFE;
|
1091 |
-
for ($i = 0; $i < $len; $i+=2) {
|
1092 |
-
$this->sortOptions[$args[$i]] = $args[$i + 1];
|
1093 |
-
}
|
1094 |
-
if (!count($this->sortOptions)) {
|
1095 |
-
$this->sortOptions = array('bogus' => true);
|
1096 |
-
}
|
1097 |
-
}
|
1098 |
-
|
1099 |
-
/**
|
1100 |
-
* Returns the file size, in bytes, or false, on failure
|
1101 |
-
*
|
1102 |
-
* Files larger than 4GB will show up as being exactly 4GB.
|
1103 |
-
*
|
1104 |
-
* @param string $filename
|
1105 |
-
* @return mixed
|
1106 |
-
* @access public
|
1107 |
-
*/
|
1108 |
-
function size($filename)
|
1109 |
-
{
|
1110 |
-
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
|
1111 |
-
return false;
|
1112 |
-
}
|
1113 |
-
|
1114 |
-
$result = $this->stat($filename);
|
1115 |
-
if ($result === false) {
|
1116 |
-
return false;
|
1117 |
-
}
|
1118 |
-
return isset($result['size']) ? $result['size'] : -1;
|
1119 |
-
}
|
1120 |
-
|
1121 |
-
/**
|
1122 |
-
* Save files / directories to cache
|
1123 |
-
*
|
1124 |
-
* @param string $path
|
1125 |
-
* @param mixed $value
|
1126 |
-
* @access private
|
1127 |
-
*/
|
1128 |
-
function _update_stat_cache($path, $value)
|
1129 |
-
{
|
1130 |
-
if ($this->use_stat_cache === false) {
|
1131 |
-
return;
|
1132 |
-
}
|
1133 |
-
|
1134 |
-
// preg_replace('#^/|/(?=/)|/$#', '', $dir) == str_replace('//', '/', trim($path, '/'))
|
1135 |
-
$dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path));
|
1136 |
-
|
1137 |
-
$temp = &$this->stat_cache;
|
1138 |
-
$max = count($dirs) - 1;
|
1139 |
-
foreach ($dirs as $i => $dir) {
|
1140 |
-
// if $temp is an object that means one of two things.
|
1141 |
-
// 1. a file was deleted and changed to a directory behind phpseclib's back
|
1142 |
-
// 2. it's a symlink. when lstat is done it's unclear what it's a symlink to
|
1143 |
-
if (is_object($temp)) {
|
1144 |
-
$temp = array();
|
1145 |
-
}
|
1146 |
-
if (!isset($temp[$dir])) {
|
1147 |
-
$temp[$dir] = array();
|
1148 |
-
}
|
1149 |
-
if ($i === $max) {
|
1150 |
-
if (is_object($temp[$dir])) {
|
1151 |
-
if (!isset($value->stat) && isset($temp[$dir]->stat)) {
|
1152 |
-
$value->stat = $temp[$dir]->stat;
|
1153 |
-
}
|
1154 |
-
if (!isset($value->lstat) && isset($temp[$dir]->lstat)) {
|
1155 |
-
$value->lstat = $temp[$dir]->lstat;
|
1156 |
-
}
|
1157 |
-
}
|
1158 |
-
$temp[$dir] = $value;
|
1159 |
-
break;
|
1160 |
-
}
|
1161 |
-
$temp = &$temp[$dir];
|
1162 |
-
}
|
1163 |
-
}
|
1164 |
-
|
1165 |
-
/**
|
1166 |
-
* Remove files / directories from cache
|
1167 |
-
*
|
1168 |
-
* @param string $path
|
1169 |
-
* @return bool
|
1170 |
-
* @access private
|
1171 |
-
*/
|
1172 |
-
function _remove_from_stat_cache($path)
|
1173 |
-
{
|
1174 |
-
$dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path));
|
1175 |
-
|
1176 |
-
$temp = &$this->stat_cache;
|
1177 |
-
$max = count($dirs) - 1;
|
1178 |
-
foreach ($dirs as $i => $dir) {
|
1179 |
-
if ($i === $max) {
|
1180 |
-
unset($temp[$dir]);
|
1181 |
-
return true;
|
1182 |
-
}
|
1183 |
-
if (!isset($temp[$dir])) {
|
1184 |
-
return false;
|
1185 |
-
}
|
1186 |
-
$temp = &$temp[$dir];
|
1187 |
-
}
|
1188 |
-
}
|
1189 |
-
|
1190 |
-
/**
|
1191 |
-
* Checks cache for path
|
1192 |
-
*
|
1193 |
-
* Mainly used by file_exists
|
1194 |
-
*
|
1195 |
-
* @param string $dir
|
1196 |
-
* @return mixed
|
1197 |
-
* @access private
|
1198 |
-
*/
|
1199 |
-
function _query_stat_cache($path)
|
1200 |
-
{
|
1201 |
-
$dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path));
|
1202 |
-
|
1203 |
-
$temp = &$this->stat_cache;
|
1204 |
-
foreach ($dirs as $dir) {
|
1205 |
-
if (!isset($temp[$dir])) {
|
1206 |
-
return null;
|
1207 |
-
}
|
1208 |
-
$temp = &$temp[$dir];
|
1209 |
-
}
|
1210 |
-
return $temp;
|
1211 |
-
}
|
1212 |
-
|
1213 |
-
/**
|
1214 |
-
* Returns general information about a file.
|
1215 |
-
*
|
1216 |
-
* Returns an array on success and false otherwise.
|
1217 |
-
*
|
1218 |
-
* @param string $filename
|
1219 |
-
* @return mixed
|
1220 |
-
* @access public
|
1221 |
-
*/
|
1222 |
-
function stat($filename)
|
1223 |
-
{
|
1224 |
-
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
|
1225 |
-
return false;
|
1226 |
-
}
|
1227 |
-
|
1228 |
-
$filename = $this->_realpath($filename);
|
1229 |
-
if ($filename === false) {
|
1230 |
-
return false;
|
1231 |
-
}
|
1232 |
-
|
1233 |
-
if ($this->use_stat_cache) {
|
1234 |
-
$result = $this->_query_stat_cache($filename);
|
1235 |
-
if (is_array($result) && isset($result['.']) && isset($result['.']->stat)) {
|
1236 |
-
return $result['.']->stat;
|
1237 |
-
}
|
1238 |
-
if (is_object($result) && isset($result->stat)) {
|
1239 |
-
return $result->stat;
|
1240 |
-
}
|
1241 |
-
}
|
1242 |
-
|
1243 |
-
$stat = $this->_stat($filename, NET_SFTP_STAT);
|
1244 |
-
if ($stat === false) {
|
1245 |
-
$this->_remove_from_stat_cache($filename);
|
1246 |
-
return false;
|
1247 |
-
}
|
1248 |
-
if (isset($stat['type'])) {
|
1249 |
-
if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) {
|
1250 |
-
$filename.= '/.';
|
1251 |
-
}
|
1252 |
-
$this->_update_stat_cache($filename, (object) array('stat' => $stat));
|
1253 |
-
return $stat;
|
1254 |
-
}
|
1255 |
-
|
1256 |
-
$pwd = $this->pwd;
|
1257 |
-
$stat['type'] = $this->chdir($filename) ?
|
1258 |
-
NET_SFTP_TYPE_DIRECTORY :
|
1259 |
-
NET_SFTP_TYPE_REGULAR;
|
1260 |
-
$this->pwd = $pwd;
|
1261 |
-
|
1262 |
-
if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) {
|
1263 |
-
$filename.= '/.';
|
1264 |
-
}
|
1265 |
-
$this->_update_stat_cache($filename, (object) array('stat' => $stat));
|
1266 |
-
|
1267 |
-
return $stat;
|
1268 |
-
}
|
1269 |
-
|
1270 |
-
/**
|
1271 |
-
* Returns general information about a file or symbolic link.
|
1272 |
-
*
|
1273 |
-
* Returns an array on success and false otherwise.
|
1274 |
-
*
|
1275 |
-
* @param string $filename
|
1276 |
-
* @return mixed
|
1277 |
-
* @access public
|
1278 |
-
*/
|
1279 |
-
function lstat($filename)
|
1280 |
-
{
|
1281 |
-
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
|
1282 |
-
return false;
|
1283 |
-
}
|
1284 |
-
|
1285 |
-
$filename = $this->_realpath($filename);
|
1286 |
-
if ($filename === false) {
|
1287 |
-
return false;
|
1288 |
-
}
|
1289 |
-
|
1290 |
-
if ($this->use_stat_cache) {
|
1291 |
-
$result = $this->_query_stat_cache($filename);
|
1292 |
-
if (is_array($result) && isset($result['.']) && isset($result['.']->lstat)) {
|
1293 |
-
return $result['.']->lstat;
|
1294 |
-
}
|
1295 |
-
if (is_object($result) && isset($result->lstat)) {
|
1296 |
-
return $result->lstat;
|
1297 |
-
}
|
1298 |
-
}
|
1299 |
-
|
1300 |
-
$lstat = $this->_stat($filename, NET_SFTP_LSTAT);
|
1301 |
-
if ($lstat === false) {
|
1302 |
-
$this->_remove_from_stat_cache($filename);
|
1303 |
-
return false;
|
1304 |
-
}
|
1305 |
-
if (isset($lstat['type'])) {
|
1306 |
-
if ($lstat['type'] == NET_SFTP_TYPE_DIRECTORY) {
|
1307 |
-
$filename.= '/.';
|
1308 |
-
}
|
1309 |
-
$this->_update_stat_cache($filename, (object) array('lstat' => $lstat));
|
1310 |
-
return $lstat;
|
1311 |
-
}
|
1312 |
-
|
1313 |
-
$stat = $this->_stat($filename, NET_SFTP_STAT);
|
1314 |
-
|
1315 |
-
if ($lstat != $stat) {
|
1316 |
-
$lstat = array_merge($lstat, array('type' => NET_SFTP_TYPE_SYMLINK));
|
1317 |
-
$this->_update_stat_cache($filename, (object) array('lstat' => $lstat));
|
1318 |
-
return $stat;
|
1319 |
-
}
|
1320 |
-
|
1321 |
-
$pwd = $this->pwd;
|
1322 |
-
$lstat['type'] = $this->chdir($filename) ?
|
1323 |
-
NET_SFTP_TYPE_DIRECTORY :
|
1324 |
-
NET_SFTP_TYPE_REGULAR;
|
1325 |
-
$this->pwd = $pwd;
|
1326 |
-
|
1327 |
-
if ($lstat['type'] == NET_SFTP_TYPE_DIRECTORY) {
|
1328 |
-
$filename.= '/.';
|
1329 |
-
}
|
1330 |
-
$this->_update_stat_cache($filename, (object) array('lstat' => $lstat));
|
1331 |
-
|
1332 |
-
return $lstat;
|
1333 |
-
}
|
1334 |
-
|
1335 |
-
/**
|
1336 |
-
* Returns general information about a file or symbolic link
|
1337 |
-
*
|
1338 |
-
* Determines information without calling \phpseclib\Net\SFTP::realpath().
|
1339 |
-
* The second parameter can be either NET_SFTP_STAT or NET_SFTP_LSTAT.
|
1340 |
-
*
|
1341 |
-
* @param string $filename
|
1342 |
-
* @param int $type
|
1343 |
-
* @return mixed
|
1344 |
-
* @access private
|
1345 |
-
*/
|
1346 |
-
function _stat($filename, $type)
|
1347 |
-
{
|
1348 |
-
// SFTPv4+ adds an additional 32-bit integer field - flags - to the following:
|
1349 |
-
$packet = pack('Na*', strlen($filename), $filename);
|
1350 |
-
if (!$this->_send_sftp_packet($type, $packet)) {
|
1351 |
-
return false;
|
1352 |
-
}
|
1353 |
-
|
1354 |
-
$response = $this->_get_sftp_packet();
|
1355 |
-
switch ($this->packet_type) {
|
1356 |
-
case NET_SFTP_ATTRS:
|
1357 |
-
return $this->_parseAttributes($response);
|
1358 |
-
case NET_SFTP_STATUS:
|
1359 |
-
$this->_logError($response);
|
1360 |
-
return false;
|
1361 |
-
}
|
1362 |
-
|
1363 |
-
user_error('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS');
|
1364 |
-
return false;
|
1365 |
-
}
|
1366 |
-
|
1367 |
-
/**
|
1368 |
-
* Truncates a file to a given length
|
1369 |
-
*
|
1370 |
-
* @param string $filename
|
1371 |
-
* @param int $new_size
|
1372 |
-
* @return bool
|
1373 |
-
* @access public
|
1374 |
-
*/
|
1375 |
-
function truncate($filename, $new_size)
|
1376 |
-
{
|
1377 |
-
$attr = pack('N3', NET_SFTP_ATTR_SIZE, $new_size / 4294967296, $new_size); // 4294967296 == 0x100000000 == 1<<32
|
1378 |
-
|
1379 |
-
return $this->_setstat($filename, $attr, false);
|
1380 |
-
}
|
1381 |
-
|
1382 |
-
/**
|
1383 |
-
* Sets access and modification time of file.
|
1384 |
-
*
|
1385 |
-
* If the file does not exist, it will be created.
|
1386 |
-
*
|
1387 |
-
* @param string $filename
|
1388 |
-
* @param int $time
|
1389 |
-
* @param int $atime
|
1390 |
-
* @return bool
|
1391 |
-
* @access public
|
1392 |
-
*/
|
1393 |
-
function touch($filename, $time = null, $atime = null)
|
1394 |
-
{
|
1395 |
-
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
|
1396 |
-
return false;
|
1397 |
-
}
|
1398 |
-
|
1399 |
-
$filename = $this->_realpath($filename);
|
1400 |
-
if ($filename === false) {
|
1401 |
-
return false;
|
1402 |
-
}
|
1403 |
-
|
1404 |
-
if (!isset($time)) {
|
1405 |
-
$time = time();
|
1406 |
-
}
|
1407 |
-
if (!isset($atime)) {
|
1408 |
-
$atime = $time;
|
1409 |
-
}
|
1410 |
-
|
1411 |
-
$flags = NET_SFTP_OPEN_WRITE | NET_SFTP_OPEN_CREATE | NET_SFTP_OPEN_EXCL;
|
1412 |
-
$attr = pack('N3', NET_SFTP_ATTR_ACCESSTIME, $time, $atime);
|
1413 |
-
$packet = pack('Na*Na*', strlen($filename), $filename, $flags, $attr);
|
1414 |
-
if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet)) {
|
1415 |
-
return false;
|
1416 |
-
}
|
1417 |
-
|
1418 |
-
$response = $this->_get_sftp_packet();
|
1419 |
-
switch ($this->packet_type) {
|
1420 |
-
case NET_SFTP_HANDLE:
|
1421 |
-
return $this->_close_handle(substr($response, 4));
|
1422 |
-
case NET_SFTP_STATUS:
|
1423 |
-
$this->_logError($response);
|
1424 |
-
break;
|
1425 |
-
default:
|
1426 |
-
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
1427 |
-
return false;
|
1428 |
-
}
|
1429 |
-
|
1430 |
-
return $this->_setstat($filename, $attr, false);
|
1431 |
-
}
|
1432 |
-
|
1433 |
-
/**
|
1434 |
-
* Changes file or directory owner
|
1435 |
-
*
|
1436 |
-
* Returns true on success or false on error.
|
1437 |
-
*
|
1438 |
-
* @param string $filename
|
1439 |
-
* @param int $uid
|
1440 |
-
* @param bool $recursive
|
1441 |
-
* @return bool
|
1442 |
-
* @access public
|
1443 |
-
*/
|
1444 |
-
function chown($filename, $uid, $recursive = false)
|
1445 |
-
{
|
1446 |
-
// quoting from <http://www.kernel.org/doc/man-pages/online/pages/man2/chown.2.html>,
|
1447 |
-
// "if the owner or group is specified as -1, then that ID is not changed"
|
1448 |
-
$attr = pack('N3', NET_SFTP_ATTR_UIDGID, $uid, -1);
|
1449 |
-
|
1450 |
-
return $this->_setstat($filename, $attr, $recursive);
|
1451 |
-
}
|
1452 |
-
|
1453 |
-
/**
|
1454 |
-
* Changes file or directory group
|
1455 |
-
*
|
1456 |
-
* Returns true on success or false on error.
|
1457 |
-
*
|
1458 |
-
* @param string $filename
|
1459 |
-
* @param int $gid
|
1460 |
-
* @param bool $recursive
|
1461 |
-
* @return bool
|
1462 |
-
* @access public
|
1463 |
-
*/
|
1464 |
-
function chgrp($filename, $gid, $recursive = false)
|
1465 |
-
{
|
1466 |
-
$attr = pack('N3', NET_SFTP_ATTR_UIDGID, -1, $gid);
|
1467 |
-
|
1468 |
-
return $this->_setstat($filename, $attr, $recursive);
|
1469 |
-
}
|
1470 |
-
|
1471 |
-
/**
|
1472 |
-
* Set permissions on a file.
|
1473 |
-
*
|
1474 |
-
* Returns the new file permissions on success or false on error.
|
1475 |
-
* If $recursive is true than this just returns true or false.
|
1476 |
-
*
|
1477 |
-
* @param int $mode
|
1478 |
-
* @param string $filename
|
1479 |
-
* @param bool $recursive
|
1480 |
-
* @return mixed
|
1481 |
-
* @access public
|
1482 |
-
*/
|
1483 |
-
function chmod($mode, $filename, $recursive = false)
|
1484 |
-
{
|
1485 |
-
if (is_string($mode) && is_int($filename)) {
|
1486 |
-
$temp = $mode;
|
1487 |
-
$mode = $filename;
|
1488 |
-
$filename = $temp;
|
1489 |
-
}
|
1490 |
-
|
1491 |
-
$attr = pack('N2', NET_SFTP_ATTR_PERMISSIONS, $mode & 07777);
|
1492 |
-
if (!$this->_setstat($filename, $attr, $recursive)) {
|
1493 |
-
return false;
|
1494 |
-
}
|
1495 |
-
if ($recursive) {
|
1496 |
-
return true;
|
1497 |
-
}
|
1498 |
-
|
1499 |
-
$filename = $this->realpath($filename);
|
1500 |
-
// rather than return what the permissions *should* be, we'll return what they actually are. this will also
|
1501 |
-
// tell us if the file actually exists.
|
1502 |
-
// incidentally, SFTPv4+ adds an additional 32-bit integer field - flags - to the following:
|
1503 |
-
$packet = pack('Na*', strlen($filename), $filename);
|
1504 |
-
if (!$this->_send_sftp_packet(NET_SFTP_STAT, $packet)) {
|
1505 |
-
return false;
|
1506 |
-
}
|
1507 |
-
|
1508 |
-
$response = $this->_get_sftp_packet();
|
1509 |
-
switch ($this->packet_type) {
|
1510 |
-
case NET_SFTP_ATTRS:
|
1511 |
-
$attrs = $this->_parseAttributes($response);
|
1512 |
-
return $attrs['permissions'];
|
1513 |
-
case NET_SFTP_STATUS:
|
1514 |
-
$this->_logError($response);
|
1515 |
-
return false;
|
1516 |
-
}
|
1517 |
-
|
1518 |
-
user_error('Expected SSH_FXP_ATTRS or SSH_FXP_STATUS');
|
1519 |
-
return false;
|
1520 |
-
}
|
1521 |
-
|
1522 |
-
/**
|
1523 |
-
* Sets information about a file
|
1524 |
-
*
|
1525 |
-
* @param string $filename
|
1526 |
-
* @param string $attr
|
1527 |
-
* @param bool $recursive
|
1528 |
-
* @return bool
|
1529 |
-
* @access private
|
1530 |
-
*/
|
1531 |
-
function _setstat($filename, $attr, $recursive)
|
1532 |
-
{
|
1533 |
-
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
|
1534 |
-
return false;
|
1535 |
-
}
|
1536 |
-
|
1537 |
-
$filename = $this->_realpath($filename);
|
1538 |
-
if ($filename === false) {
|
1539 |
-
return false;
|
1540 |
-
}
|
1541 |
-
|
1542 |
-
$this->_remove_from_stat_cache($filename);
|
1543 |
-
|
1544 |
-
if ($recursive) {
|
1545 |
-
$i = 0;
|
1546 |
-
$result = $this->_setstat_recursive($filename, $attr, $i);
|
1547 |
-
$this->_read_put_responses($i);
|
1548 |
-
return $result;
|
1549 |
-
}
|
1550 |
-
|
1551 |
-
// SFTPv4+ has an additional byte field - type - that would need to be sent, as well. setting it to
|
1552 |
-
// SSH_FILEXFER_TYPE_UNKNOWN might work. if not, we'd have to do an SSH_FXP_STAT before doing an SSH_FXP_SETSTAT.
|
1553 |
-
if (!$this->_send_sftp_packet(NET_SFTP_SETSTAT, pack('Na*a*', strlen($filename), $filename, $attr))) {
|
1554 |
-
return false;
|
1555 |
-
}
|
1556 |
-
|
1557 |
-
/*
|
1558 |
-
"Because some systems must use separate system calls to set various attributes, it is possible that a failure
|
1559 |
-
response will be returned, but yet some of the attributes may be have been successfully modified. If possible,
|
1560 |
-
servers SHOULD avoid this situation; however, clients MUST be aware that this is possible."
|
1561 |
-
|
1562 |
-
-- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.6
|
1563 |
-
*/
|
1564 |
-
$response = $this->_get_sftp_packet();
|
1565 |
-
if ($this->packet_type != NET_SFTP_STATUS) {
|
1566 |
-
user_error('Expected SSH_FXP_STATUS');
|
1567 |
-
return false;
|
1568 |
-
}
|
1569 |
-
|
1570 |
-
if (strlen($response) < 4) {
|
1571 |
-
return false;
|
1572 |
-
}
|
1573 |
-
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
1574 |
-
if ($status != NET_SFTP_STATUS_OK) {
|
1575 |
-
$this->_logError($response, $status);
|
1576 |
-
return false;
|
1577 |
-
}
|
1578 |
-
|
1579 |
-
return true;
|
1580 |
-
}
|
1581 |
-
|
1582 |
-
/**
|
1583 |
-
* Recursively sets information on directories on the SFTP server
|
1584 |
-
*
|
1585 |
-
* Minimizes directory lookups and SSH_FXP_STATUS requests for speed.
|
1586 |
-
*
|
1587 |
-
* @param string $path
|
1588 |
-
* @param string $attr
|
1589 |
-
* @param int $i
|
1590 |
-
* @return bool
|
1591 |
-
* @access private
|
1592 |
-
*/
|
1593 |
-
function _setstat_recursive($path, $attr, &$i)
|
1594 |
-
{
|
1595 |
-
if (!$this->_read_put_responses($i)) {
|
1596 |
-
return false;
|
1597 |
-
}
|
1598 |
-
$i = 0;
|
1599 |
-
$entries = $this->_list($path, true);
|
1600 |
-
|
1601 |
-
if ($entries === false) {
|
1602 |
-
return $this->_setstat($path, $attr, false);
|
1603 |
-
}
|
1604 |
-
|
1605 |
-
// normally $entries would have at least . and .. but it might not if the directories
|
1606 |
-
// permissions didn't allow reading
|
1607 |
-
if (empty($entries)) {
|
1608 |
-
return false;
|
1609 |
-
}
|
1610 |
-
|
1611 |
-
unset($entries['.'], $entries['..']);
|
1612 |
-
foreach ($entries as $filename => $props) {
|
1613 |
-
if (!isset($props['type'])) {
|
1614 |
-
return false;
|
1615 |
-
}
|
1616 |
-
|
1617 |
-
$temp = $path . '/' . $filename;
|
1618 |
-
if ($props['type'] == NET_SFTP_TYPE_DIRECTORY) {
|
1619 |
-
if (!$this->_setstat_recursive($temp, $attr, $i)) {
|
1620 |
-
return false;
|
1621 |
-
}
|
1622 |
-
} else {
|
1623 |
-
if (!$this->_send_sftp_packet(NET_SFTP_SETSTAT, pack('Na*a*', strlen($temp), $temp, $attr))) {
|
1624 |
-
return false;
|
1625 |
-
}
|
1626 |
-
|
1627 |
-
$i++;
|
1628 |
-
|
1629 |
-
if ($i >= NET_SFTP_QUEUE_SIZE) {
|
1630 |
-
if (!$this->_read_put_responses($i)) {
|
1631 |
-
return false;
|
1632 |
-
}
|
1633 |
-
$i = 0;
|
1634 |
-
}
|
1635 |
-
}
|
1636 |
-
}
|
1637 |
-
|
1638 |
-
if (!$this->_send_sftp_packet(NET_SFTP_SETSTAT, pack('Na*a*', strlen($path), $path, $attr))) {
|
1639 |
-
return false;
|
1640 |
-
}
|
1641 |
-
|
1642 |
-
$i++;
|
1643 |
-
|
1644 |
-
if ($i >= NET_SFTP_QUEUE_SIZE) {
|
1645 |
-
if (!$this->_read_put_responses($i)) {
|
1646 |
-
return false;
|
1647 |
-
}
|
1648 |
-
$i = 0;
|
1649 |
-
}
|
1650 |
-
|
1651 |
-
return true;
|
1652 |
-
}
|
1653 |
-
|
1654 |
-
/**
|
1655 |
-
* Return the target of a symbolic link
|
1656 |
-
*
|
1657 |
-
* @param string $link
|
1658 |
-
* @return mixed
|
1659 |
-
* @access public
|
1660 |
-
*/
|
1661 |
-
function readlink($link)
|
1662 |
-
{
|
1663 |
-
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
|
1664 |
-
return false;
|
1665 |
-
}
|
1666 |
-
|
1667 |
-
$link = $this->_realpath($link);
|
1668 |
-
|
1669 |
-
if (!$this->_send_sftp_packet(NET_SFTP_READLINK, pack('Na*', strlen($link), $link))) {
|
1670 |
-
return false;
|
1671 |
-
}
|
1672 |
-
|
1673 |
-
$response = $this->_get_sftp_packet();
|
1674 |
-
switch ($this->packet_type) {
|
1675 |
-
case NET_SFTP_NAME:
|
1676 |
-
break;
|
1677 |
-
case NET_SFTP_STATUS:
|
1678 |
-
$this->_logError($response);
|
1679 |
-
return false;
|
1680 |
-
default:
|
1681 |
-
user_error('Expected SSH_FXP_NAME or SSH_FXP_STATUS');
|
1682 |
-
return false;
|
1683 |
-
}
|
1684 |
-
|
1685 |
-
if (strlen($response) < 4) {
|
1686 |
-
return false;
|
1687 |
-
}
|
1688 |
-
extract(unpack('Ncount', $this->_string_shift($response, 4)));
|
1689 |
-
// the file isn't a symlink
|
1690 |
-
if (!$count) {
|
1691 |
-
return false;
|
1692 |
-
}
|
1693 |
-
|
1694 |
-
if (strlen($response) < 4) {
|
1695 |
-
return false;
|
1696 |
-
}
|
1697 |
-
extract(unpack('Nlength', $this->_string_shift($response, 4)));
|
1698 |
-
return $this->_string_shift($response, $length);
|
1699 |
-
}
|
1700 |
-
|
1701 |
-
/**
|
1702 |
-
* Create a symlink
|
1703 |
-
*
|
1704 |
-
* symlink() creates a symbolic link to the existing target with the specified name link.
|
1705 |
-
*
|
1706 |
-
* @param string $target
|
1707 |
-
* @param string $link
|
1708 |
-
* @return bool
|
1709 |
-
* @access public
|
1710 |
-
*/
|
1711 |
-
function symlink($target, $link)
|
1712 |
-
{
|
1713 |
-
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
|
1714 |
-
return false;
|
1715 |
-
}
|
1716 |
-
|
1717 |
-
//$target = $this->_realpath($target);
|
1718 |
-
$link = $this->_realpath($link);
|
1719 |
-
|
1720 |
-
$packet = pack('Na*Na*', strlen($target), $target, strlen($link), $link);
|
1721 |
-
if (!$this->_send_sftp_packet(NET_SFTP_SYMLINK, $packet)) {
|
1722 |
-
return false;
|
1723 |
-
}
|
1724 |
-
|
1725 |
-
$response = $this->_get_sftp_packet();
|
1726 |
-
if ($this->packet_type != NET_SFTP_STATUS) {
|
1727 |
-
user_error('Expected SSH_FXP_STATUS');
|
1728 |
-
return false;
|
1729 |
-
}
|
1730 |
-
|
1731 |
-
if (strlen($response) < 4) {
|
1732 |
-
return false;
|
1733 |
-
}
|
1734 |
-
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
1735 |
-
if ($status != NET_SFTP_STATUS_OK) {
|
1736 |
-
$this->_logError($response, $status);
|
1737 |
-
return false;
|
1738 |
-
}
|
1739 |
-
|
1740 |
-
return true;
|
1741 |
-
}
|
1742 |
-
|
1743 |
-
/**
|
1744 |
-
* Creates a directory.
|
1745 |
-
*
|
1746 |
-
* @param string $dir
|
1747 |
-
* @return bool
|
1748 |
-
* @access public
|
1749 |
-
*/
|
1750 |
-
function mkdir($dir, $mode = -1, $recursive = false)
|
1751 |
-
{
|
1752 |
-
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
|
1753 |
-
return false;
|
1754 |
-
}
|
1755 |
-
|
1756 |
-
$dir = $this->_realpath($dir);
|
1757 |
-
// by not providing any permissions, hopefully the server will use the logged in users umask - their
|
1758 |
-
// default permissions.
|
1759 |
-
$attr = $mode == -1 ? "\0\0\0\0" : pack('N2', NET_SFTP_ATTR_PERMISSIONS, $mode & 07777);
|
1760 |
-
|
1761 |
-
if ($recursive) {
|
1762 |
-
$dirs = explode('/', preg_replace('#/(?=/)|/$#', '', $dir));
|
1763 |
-
if (empty($dirs[0])) {
|
1764 |
-
array_shift($dirs);
|
1765 |
-
$dirs[0] = '/' . $dirs[0];
|
1766 |
-
}
|
1767 |
-
for ($i = 0; $i < count($dirs); $i++) {
|
1768 |
-
$temp = array_slice($dirs, 0, $i + 1);
|
1769 |
-
$temp = implode('/', $temp);
|
1770 |
-
$result = $this->_mkdir_helper($temp, $attr);
|
1771 |
-
}
|
1772 |
-
return $result;
|
1773 |
-
}
|
1774 |
-
|
1775 |
-
return $this->_mkdir_helper($dir, $attr);
|
1776 |
-
}
|
1777 |
-
|
1778 |
-
/**
|
1779 |
-
* Helper function for directory creation
|
1780 |
-
*
|
1781 |
-
* @param string $dir
|
1782 |
-
* @return bool
|
1783 |
-
* @access private
|
1784 |
-
*/
|
1785 |
-
function _mkdir_helper($dir, $attr)
|
1786 |
-
{
|
1787 |
-
if (!$this->_send_sftp_packet(NET_SFTP_MKDIR, pack('Na*a*', strlen($dir), $dir, $attr))) {
|
1788 |
-
return false;
|
1789 |
-
}
|
1790 |
-
|
1791 |
-
$response = $this->_get_sftp_packet();
|
1792 |
-
if ($this->packet_type != NET_SFTP_STATUS) {
|
1793 |
-
user_error('Expected SSH_FXP_STATUS');
|
1794 |
-
return false;
|
1795 |
-
}
|
1796 |
-
|
1797 |
-
if (strlen($response) < 4) {
|
1798 |
-
return false;
|
1799 |
-
}
|
1800 |
-
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
1801 |
-
if ($status != NET_SFTP_STATUS_OK) {
|
1802 |
-
$this->_logError($response, $status);
|
1803 |
-
return false;
|
1804 |
-
}
|
1805 |
-
|
1806 |
-
return true;
|
1807 |
-
}
|
1808 |
-
|
1809 |
-
/**
|
1810 |
-
* Removes a directory.
|
1811 |
-
*
|
1812 |
-
* @param string $dir
|
1813 |
-
* @return bool
|
1814 |
-
* @access public
|
1815 |
-
*/
|
1816 |
-
function rmdir($dir)
|
1817 |
-
{
|
1818 |
-
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
|
1819 |
-
return false;
|
1820 |
-
}
|
1821 |
-
|
1822 |
-
$dir = $this->_realpath($dir);
|
1823 |
-
if ($dir === false) {
|
1824 |
-
return false;
|
1825 |
-
}
|
1826 |
-
|
1827 |
-
if (!$this->_send_sftp_packet(NET_SFTP_RMDIR, pack('Na*', strlen($dir), $dir))) {
|
1828 |
-
return false;
|
1829 |
-
}
|
1830 |
-
|
1831 |
-
$response = $this->_get_sftp_packet();
|
1832 |
-
if ($this->packet_type != NET_SFTP_STATUS) {
|
1833 |
-
user_error('Expected SSH_FXP_STATUS');
|
1834 |
-
return false;
|
1835 |
-
}
|
1836 |
-
|
1837 |
-
if (strlen($response) < 4) {
|
1838 |
-
return false;
|
1839 |
-
}
|
1840 |
-
extract(unpack('Nstatus', $this->_string_shift($response, 4)));
|
1841 |
-
if ($status != NET_SFTP_STATUS_OK) {
|
1842 |
-
// presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED?
|
1843 |
-
$this->_logError($response, $status);
|
1844 |
-
return false;
|
1845 |
-
}
|
1846 |
-
|
1847 |
-
$this->_remove_from_stat_cache($dir);
|
1848 |
-
// the following will do a soft delete, which would be useful if you deleted a file
|
1849 |
-
// and then tried to do a stat on the deleted file. the above, in contrast, does
|
1850 |
-
// a hard delete
|
1851 |
-
//$this->_update_stat_cache($dir, false);
|
1852 |
-
|
1853 |
-
return true;
|
1854 |
-
}
|
1855 |
-
|
1856 |
-
/**
|
1857 |
-
* Uploads a file to the SFTP server.
|
1858 |
-
*
|
1859 |
-
* By default, \phpseclib\Net\SFTP::put() does not read from the local filesystem. $data is dumped directly into $remote_file.
|
1860 |
-
* So, for example, if you set $data to 'filename.ext' and then do \phpseclib\Net\SFTP::get(), you will get a file, twelve bytes
|
1861 |
-
* long, containing 'filename.ext' as its contents.
|
1862 |
-
*
|
1863 |
-
* Setting $mode to self::SOURCE_LOCAL_FILE will change the above behavior. With self::SOURCE_LOCAL_FILE, $remote_file will
|
1864 |
-
* contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how
|
1865 |
-
* large $remote_file will be, as well.
|
1866 |
-
*
|
1867 |
-
* Setting $mode to self::SOURCE_CALLBACK will use $data as callback function, which gets only one parameter -- number of bytes to return, and returns a string if there is some data or null if there is no more data
|
1868 |
-
*
|
1869 |
-
* If $data is a resource then it'll be used as a resource instead.
|
1870 |
-
*
|
1871 |
-
* Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take
|
1872 |
-
* care of that, yourself.
|
1873 |
-
*
|
1874 |
-
* $mode can take an additional two parameters - self::RESUME and self::RESUME_START. These are bitwise AND'd with
|
1875 |
-
* $mode. So if you want to resume upload of a 300mb file on the local file system you'd set $mode to the following:
|
1876 |
-
*
|
1877 |
-
* self::SOURCE_LOCAL_FILE | self::RESUME
|
1878 |
-
*
|
1879 |
-
* If you wanted to simply append the full contents of a local file to the full contents of a remote file you'd replace
|
1880 |
-
* self::RESUME with self::RESUME_START.
|
1881 |
-
*
|
1882 |
-
* If $mode & (self::RESUME | self::RESUME_START) then self::RESUME_START will be assumed.
|
1883 |
-
*
|
1884 |
-
* $start and $local_start give you more fine grained control over this process and take precident over self::RESUME
|
1885 |
-
* when they're non-negative. ie. $start could let you write at the end of a file (like self::RESUME) or in the middle
|
1886 |
-
* of one. $local_start could let you start your reading from the end of a file (like self::RESUME_START) or in the
|
1887 |
-
* middle of one.
|
1888 |
-
*
|
1889 |
-
* Setting $local_start to > 0 or $mode | self::RESUME_START doesn't do anything unless $mode | self::SOURCE_LOCAL_FILE.
|
1890 |
-
*
|
1891 |
-
* @param string $remote_file
|
1892 |
-
* @param string|resource $data
|
1893 |
-
* @param int $mode
|
1894 |
-
* @param int $start
|
1895 |
-
* @param int $local_start
|
1896 |
-
* @param callable|null $progressCallback
|
1897 |
-
* @return bool
|
1898 |
-
* @access public
|
1899 |
-
* @internal ASCII mode for SFTPv4/5/6 can be supported by adding a new function - \phpseclib\Net\SFTP::setMode().
|
1900 |
-
*/
|
1901 |
-
function put($remote_file, $data, $mode = self::SOURCE_STRING, $start = -1, $local_start = -1, $progressCallback = null)
|
1902 |
-
{
|
1903 |
-
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
|
1904 |
-
return false;
|
1905 |
-
}
|
1906 |
-
|
1907 |
-
$remote_file = $this->_realpath($remote_file);
|
1908 |
-
if ($remote_file === false) {
|
1909 |
-
return false;
|
1910 |
-
}
|
1911 |
-
|
1912 |
-
$this->_remove_from_stat_cache($remote_file);
|
1913 |
-
|
1914 |
-
$flags = NET_SFTP_OPEN_WRITE | NET_SFTP_OPEN_CREATE;
|
1915 |
-
// according to the SFTP specs, NET_SFTP_OPEN_APPEND should "force all writes to append data at the end of the file."
|
1916 |
-
// in practice, it doesn't seem to do that.
|
1917 |
-
//$flags|= ($mode & self::RESUME) ? NET_SFTP_OPEN_APPEND : NET_SFTP_OPEN_TRUNCATE;
|
1918 |
-
|
1919 |
-
if ($start >= 0) {
|
1920 |
-
$offset = $start;
|
1921 |
-
} elseif ($mode & self::RESUME) {
|
1922 |
-
// if NET_SFTP_OPEN_APPEND worked as it should _size() wouldn't need to be called
|
1923 |
-
$size = $this->size($remote_file);
|
1924 |
-
$offset = $size !== false ? $size : 0;
|
1925 |
-
} else {
|
1926 |
-
$offset = 0;
|
1927 |
-
$flags|= NET_SFTP_OPEN_TRUNCATE;
|
1928 |
-
}
|
1929 |
-
|
1930 |
-
$packet = pack('Na*N2', strlen($remote_file), $remote_file, $flags, 0);
|
1931 |
-
if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet)) {
|
1932 |
-
return false;
|
1933 |
-
}
|
1934 |
-
|
1935 |
-
$response = $this->_get_sftp_packet();
|
1936 |
-
switch ($this->packet_type) {
|
1937 |
-
case NET_SFTP_HANDLE:
|
1938 |
-
$handle = substr($response, 4);
|
1939 |
-
break;
|
1940 |
-
case NET_SFTP_STATUS:
|
1941 |
-
$this->_logError($response);
|
1942 |
-
return false;
|
1943 |
-
default:
|
1944 |
-
user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS');
|
1945 |
-
return false;
|
1946 |
-
}
|
1947 |
-
|
1948 |
-
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.3
|
1949 |
-
$dataCallback = false;
|
1950 |
-
switch (true) {
|
1951 |
-
case $mode & self::S
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|