Post SMTP Mailer/Email Log - Version 2.2-beta.2

Version Description

  • 2022-11-02 =
  • NEW
  • Added New Socket/ Email Service Postmark
  • Added New Socket/ Email Service SparkPost
  • IMPROVEMENTS
  • SSRF Prevention
  • PHP 8.0+ Compatibility Added
  • SQL Warning Removed
  • MailGun SDK Updated to Latest Version
  • Compatibility with BackupBuddy added
  • Freemius SDK Updated
  • FIXES
  • Multisite Plugin Update
  • Additional Headers were not saved properly in some cases
  • Import Button was not working in some cases
Download this release

Release Info

Developer wpexpertsio
Plugin Icon 128x128 Post SMTP Mailer/Email Log
Version 2.2-beta.2
Comparing to
See all releases

Code changes from version 2.2-beta.1 to 2.2-beta.2

Files changed (52) hide show
  1. .gitignore +1 -0
  2. Postman/Extensions/Core/Notifications/INotify.php +6 -6
  3. Postman/Extensions/Core/Notifications/PostmanMailNotify.php +13 -13
  4. Postman/Extensions/Core/Notifications/PostmanNotify.php +252 -252
  5. Postman/Extensions/Core/Notifications/PostmanNotifyOptions.php +67 -67
  6. Postman/Extensions/Core/Notifications/PostmanPushoverNotify.php +33 -33
  7. Postman/Extensions/Core/Notifications/PostmanSlackNotify.php +40 -40
  8. Postman/Extensions/Core/StatusSolution.php +60 -60
  9. Postman/Localize.php +29 -29
  10. Postman/Phpmailer/PostsmtpMailer.php +173 -173
  11. Postman/Postman-Auth/PostmanAbstractAuthenticationManager.php +171 -171
  12. Postman/Postman-Auth/PostmanAuthenticationManager.php +18 -18
  13. Postman/Postman-Auth/PostmanAuthenticationManagerFactory.php +57 -57
  14. Postman/Postman-Auth/PostmanGoogleAuthenticationManager.php +122 -122
  15. Postman/Postman-Auth/PostmanMicrosoftAuthenticationManager.php +107 -107
  16. Postman/Postman-Auth/PostmanNonOAuthAuthenticationManager.php +46 -46
  17. Postman/Postman-Auth/PostmanStateIdMissingException.php +7 -7
  18. Postman/Postman-Auth/PostmanYahooAuthenticationManager.php +136 -136
  19. Postman/Postman-Configuration/PostmanConfigurationController.php +1099 -1099
  20. Postman/Postman-Configuration/PostmanImportableConfiguration.php +691 -685
  21. Postman/Postman-Configuration/PostmanRegisterConfigurationSettings.php +451 -451
  22. Postman/Postman-Configuration/PostmanSmtpDiscovery.php +237 -237
  23. Postman/Postman-Configuration/postman_manual_config.js +112 -112
  24. Postman/Postman-Configuration/postman_wizard.js +697 -697
  25. Postman/Postman-Connectivity-Test/Postman-PortTest.php +286 -286
  26. Postman/Postman-Connectivity-Test/PostmanConnectivityTestController.php +382 -382
  27. Postman/Postman-Connectivity-Test/postman_port_test.js +336 -336
  28. Postman/Postman-Connectivity-Test/registered-domain-libs-master/PHP/effectiveTLDs.inc.php +6484 -6484
  29. Postman/Postman-Connectivity-Test/registered-domain-libs-master/PHP/regDomain.class.php +120 -120
  30. Postman/Postman-Connectivity-Test/registered-domain-libs-master/PHP/regDomain.inc.php +62 -62
  31. Postman/Postman-Connectivity-Test/registered-domain-libs-master/PHP/test-regDomain.php +51 -51
  32. Postman/Postman-Connectivity-Test/registered-domain-libs-master/README.txt +56 -56
  33. Postman/Postman-Connectivity-Test/registered-domain-libs-master/generateEffectiveTLDs.php +213 -213
  34. Postman/Postman-Controller/PostmanAdminPointer.php +116 -116
  35. Postman/Postman-Controller/PostmanDashboardWidgetController.php +160 -160
  36. Postman/Postman-Controller/PostmanManageConfigurationAjaxHandler.php +68 -68
  37. Postman/Postman-Controller/PostmanWelcomeController.php +217 -217
  38. Postman/Postman-Diagnostic-Test/PostmanDiagnosticTestController.php +300 -300
  39. Postman/Postman-Diagnostic-Test/postman_diagnostics.js +19 -19
  40. Postman/Postman-Email-Log/PostmanEmailLogController.php +513 -513
  41. Postman/Postman-Email-Log/PostmanEmailLogPostType.php +51 -51
  42. Postman/Postman-Email-Log/PostmanEmailLogService.php +340 -340
  43. Postman/Postman-Email-Log/PostmanEmailLogView.php +454 -454
  44. Postman/Postman-Mail/PostmanContactForm7.php +42 -42
  45. Postman/Postman-Mail/PostmanDefaultModuleTransport.php +179 -179
  46. Postman/Postman-Mail/PostmanEmailAddress.php +94 -94
  47. Postman/Postman-Mail/PostmanGmailApiModuleTransport.php +308 -308
  48. Postman/Postman-Mail/PostmanGmailApiModuleZendMailTransport.php +277 -277
  49. Postman/Postman-Mail/PostmanMailEngine.php +14 -14
  50. Postman/Postman-Mail/PostmanMailgunMailEngine.php +273 -273
  51. Postman/Postman-Mail/PostmanMailgunTransport.php +293 -293
  52. Postman/Postman-Mail/PostmanMandrillMailEngine.php +0 -192
.gitignore ADDED
@@ -0,0 +1 @@
 
1
+ .idea
Postman/Extensions/Core/Notifications/INotify.php CHANGED
@@ -1,7 +1,7 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
- interface Postman_Notify {
6
- public function send_message( $message );
7
  }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+ interface Postman_Notify {
6
+ public function send_message( $message );
7
  }
Postman/Extensions/Core/Notifications/PostmanMailNotify.php CHANGED
@@ -1,14 +1,14 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
- class PostmanMailNotify implements Postman_Notify {
6
-
7
- public function send_message($message)
8
- {
9
- $to_email = apply_filters( 'post_smtp_notify_email',get_bloginfo( 'admin_email' ) );
10
- $domain = get_bloginfo( 'url' );
11
-
12
- mail( $to_email, "{$domain}: " . __( 'Post SMTP email error', 'post-smtp' ), $message , '', "-f{$to_email}" );
13
- }
14
  }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+ class PostmanMailNotify implements Postman_Notify {
6
+
7
+ public function send_message($message)
8
+ {
9
+ $to_email = apply_filters( 'post_smtp_notify_email',get_bloginfo( 'admin_email' ) );
10
+ $domain = get_bloginfo( 'url' );
11
+
12
+ mail( $to_email, "{$domain}: " . __( 'Post SMTP email error', 'post-smtp' ), $message , '', "-f{$to_email}" );
13
+ }
14
  }
Postman/Extensions/Core/Notifications/PostmanNotify.php CHANGED
@@ -1,252 +1,252 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- require_once 'INotify.php';
7
- require_once 'PostmanMailNotify.php';
8
- require_once 'PostmanPushoverNotify.php';
9
- require_once 'PostmanSlackNotify.php';
10
- require_once 'PostmanNotifyOptions.php';
11
-
12
- class PostmanNotify {
13
-
14
- const NOTIFICATIONS_OPTIONS = 'postman_notifications_options';
15
- const NOTIFICATIONS_SECTION = 'postman_notifications_section';
16
- const NOTIFICATIONS_PUSHOVER_CRED = 'postman_pushover_cred';
17
- const NOTIFICATIONS_SLACK_CRED = 'postman_slack_cred';
18
-
19
- private $options;
20
-
21
- public function __construct() {
22
-
23
- $this->options = PostmanNotifyOptions::getInstance();
24
-
25
- add_filter( 'post_smtp_admin_tabs', array( $this, 'tabs' ) );
26
- add_action( 'post_smtp_settings_menu', array( $this, 'menu' ) );
27
- add_action( 'post_smtp_settings_fields', array( $this, 'settings' ) );
28
- add_action( 'post_smtp_on_failed', array( $this, 'notify' ), 10, 5 );
29
- add_filter( 'post_smtp_sanitize', array( $this, 'sanitize' ), 10, 3 );
30
- }
31
-
32
- public function menu() {
33
- print '<section id="notifications">';
34
- do_settings_sections( self::NOTIFICATIONS_OPTIONS );
35
-
36
- $currentKey = $this->options->getNotificationService();
37
- $pushover = $currentKey == 'pushover' ? 'block' : 'none';
38
- $slack = $currentKey == 'slack' ? 'block' : 'none';
39
-
40
- echo '<div id="pushover_cred" style="display: ' . $pushover . ';">';
41
- do_settings_sections( self::NOTIFICATIONS_PUSHOVER_CRED );
42
- echo '</div>';
43
-
44
- echo '<div id="slack_cred" style="display: ' . $slack . ';">';
45
- do_settings_sections( self::NOTIFICATIONS_SLACK_CRED );
46
- echo '</div>';
47
-
48
- do_action( 'post_smtp_notification_settings' );
49
-
50
- print '</section>';
51
- }
52
-
53
- public function sanitize($new_input, $input, $sanitizer) {
54
- // Notifications
55
- $sanitizer->sanitizeString( 'Pushover Service', PostmanNotifyOptions::NOTIFICATION_SERVICE, $input, $new_input, $this->options->getNotificationService() );
56
- $sanitizer->sanitizePassword( 'Pushover Username', PostmanNotifyOptions::PUSHOVER_USER, $input, $new_input, $this->options->getPushoverUser() );
57
- $sanitizer->sanitizePassword( 'Pushover Token', PostmanNotifyOptions::PUSHOVER_TOKEN, $input, $new_input, $this->options->getPushoverToken() );
58
- $sanitizer->sanitizePassword( 'Slack Token', PostmanNotifyOptions::SLACK_TOKEN, $input, $new_input, $this->options->getSlackToken() );
59
-
60
- // Chrome extension
61
- $sanitizer->sanitizeString( 'Push Chrome Extension', PostmanNotifyOptions::NOTIFICATION_USE_CHROME, $input, $new_input );
62
- $sanitizer->sanitizePassword( 'Push Chrome Extension UID', PostmanNotifyOptions::NOTIFICATION_CHROME_UID, $input, $new_input, $this->options->getNotificationChromeUid() );
63
-
64
- return $new_input;
65
- }
66
-
67
- public function tabs($tabs) {
68
- $tabs['notifications'] = __( 'Notifications', 'post-smtp' );
69
-
70
- return $tabs;
71
- }
72
-
73
- public function settings() {
74
- // Notifications
75
- add_settings_section( self::NOTIFICATIONS_SECTION, _x( 'Notifications Settings', 'Configuration Section Title', 'post-smtp' ), array(
76
- $this,
77
- 'printNotificationsSectionInfo',
78
- ), self::NOTIFICATIONS_OPTIONS );
79
-
80
- add_settings_field( PostmanNotifyOptions::NOTIFICATION_SERVICE, _x( 'Notification Service', 'Configuration Input Field', 'post-smtp' ), array(
81
- $this,
82
- 'notification_service_callback',
83
- ), self::NOTIFICATIONS_OPTIONS, self::NOTIFICATIONS_SECTION );
84
-
85
- // Pushover
86
- add_settings_section( 'pushover_credentials', _x( 'Pushover Credentials', 'Configuration Section Title', 'post-smtp' ), array(
87
- $this,
88
- 'printNotificationsSectionInfo',
89
- ), self::NOTIFICATIONS_PUSHOVER_CRED );
90
-
91
- add_settings_field( PostmanNotifyOptions::PUSHOVER_USER, _x( 'Pushover User Key', 'Configuration Input Field', 'post-smtp' ), array(
92
- $this,
93
- 'pushover_user_callback',
94
- ), self::NOTIFICATIONS_PUSHOVER_CRED, 'pushover_credentials' );
95
-
96
- add_settings_field( PostmanNotifyOptions::PUSHOVER_TOKEN, _x( 'Pushover App Token', 'Configuration Input Field', 'post-smtp' ), array(
97
- $this,
98
- 'pushover_token_callback',
99
- ), self::NOTIFICATIONS_PUSHOVER_CRED, 'pushover_credentials' );
100
-
101
- // Slack
102
- add_settings_section( 'slack_credentials', _x( 'Slack Credentials', 'Configuration Section Title', 'post-smtp' ), array(
103
- $this,
104
- 'printNotificationsSectionInfo',
105
- ), self::NOTIFICATIONS_SLACK_CRED );
106
-
107
- add_settings_field( PostmanNotifyOptions::SLACK_TOKEN, _x( 'Slack Webhook', 'Configuration Input Field', 'post-smtp' ), array(
108
- $this,
109
- 'slack_token_callback',
110
- ), self::NOTIFICATIONS_SLACK_CRED, 'slack_credentials' );
111
-
112
- add_settings_field( PostmanNotifyOptions::NOTIFICATION_USE_CHROME, _x( 'Push to chrome extension', 'Configuration Input Field', 'post-smtp' ), array(
113
- $this,
114
- 'notification_use_chrome_callback',
115
- ), self::NOTIFICATIONS_OPTIONS, self::NOTIFICATIONS_SECTION );
116
-
117
- add_settings_field( 'notification_chrome_uid', _x( 'Chrome Extension UID', 'Configuration Input Field', 'post-smtp' ), array(
118
- $this,
119
- 'notification_chrome_uid_callback',
120
- ), self::NOTIFICATIONS_OPTIONS, self::NOTIFICATIONS_SECTION );
121
- }
122
-
123
- /**
124
- * Print the Section text
125
- */
126
- public function printNotificationsSectionInfo() {
127
- }
128
-
129
- public function notification_service_callback() {
130
- $inputDescription = __( 'Select the notification service you want to recieve alerts about failed emails.' );
131
-
132
- $options = apply_filters('post_smtp_notification_service', array(
133
- 'none' => __( 'None', 'post-smtp' ),
134
- 'default' => __( 'WP Admin Email', 'post-smtp' ),
135
- 'pushover' => __( 'Pushover', 'post-smtp' ),
136
- 'slack' => __( 'Slack', 'post-smtp' ),
137
- ));
138
-
139
- printf( '<select id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]">', 'postman_options', PostmanNotifyOptions::NOTIFICATION_SERVICE );
140
- $currentKey = $this->options->getNotificationService();
141
-
142
- foreach ( $options as $key => $label ) {
143
- $this->printSelectOption( $label, $key, $currentKey );
144
- }
145
-
146
- printf( '</select><br/><span class="postman_input_description">%s</span>', $inputDescription );
147
- }
148
-
149
- public function notification_use_chrome_callback() {
150
- $value = $this->options->useChromeExtension();
151
- printf( '<input type="checkbox" id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]" %3$s />', 'postman_options', PostmanNotifyOptions::NOTIFICATION_USE_CHROME, $value ? 'checked="checked"' : '' );
152
- }
153
-
154
- public function notification_chrome_uid_callback() {
155
- printf( '<input type="password" id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', 'postman_options', 'notification_chrome_uid', PostmanUtils::obfuscatePassword( $this->options->getNotificationChromeUid() ) );
156
- }
157
-
158
- public function pushover_user_callback() {
159
- printf( '<input type="password" id="pushover_user" name="%s[%s]" value="%s" />', 'postman_options', PostmanNotifyOptions::PUSHOVER_USER, $this->options->getPushoverUser() );
160
- }
161
-
162
- public function pushover_token_callback() {
163
- printf( '<input type="password" id="pushover_token" name="%s[%s]" value="%s" />', 'postman_options', PostmanNotifyOptions::PUSHOVER_TOKEN, $this->options->getPushoverToken() );
164
- }
165
-
166
- public function slack_token_callback() {
167
- printf( '<input type="password" id="slack_token" name="%s[%s]" value="%s" />', 'postman_options', PostmanNotifyOptions::SLACK_TOKEN, $this->options->getSlackToken() );
168
- echo '<a target="_blank" href="https://slack.postmansmtp.com/">' . __( 'Get your webhook URL here', 'post-smtp' ) . '</a>';
169
-
170
- }
171
-
172
- /**
173
- * @param PostmanEmailLog $log
174
- * @param PostmanMessage $message
175
- * @param string $transcript
176
- * @param PostmanTransport $transport
177
- * @param string $errorMessage
178
- */
179
- public function notify ($log, $postmanMessage, $transcript, $transport, $errorMessage ) {
180
- $message = __( 'You getting this message because an error detected while delivered your email.', 'post-smtp' );
181
- $message .= "\r\n" . sprintf( __( 'For the domain: %1$s','post-smtp' ), get_bloginfo('url') );
182
- $message .= "\r\n" . __( 'The log to paste when you open a support issue:', 'post-smtp' ) . "\r\n";
183
-
184
- if ( $errorMessage && ! empty( $errorMessage ) ) {
185
-
186
- $message = $message . $errorMessage;
187
-
188
- $notification_service = PostmanNotifyOptions::getInstance()->getNotificationService();
189
- switch ($notification_service) {
190
- case 'none':
191
- $notifyer = false;
192
- break;
193
- case 'default':
194
- $notifyer = new PostmanMailNotify;
195
- break;
196
- case 'pushover':
197
- $notifyer = new PostmanPushoverNotify;
198
- break;
199
- case 'slack':
200
- $notifyer = new PostmanSlackNotify;
201
- break;
202
- default:
203
- $notifyer = new PostmanMailNotify;
204
- }
205
-
206
- $notifyer = apply_filters('post_smtp_notifier', $notifyer, $notification_service);
207
-
208
- // Notifications
209
- if ( $notifyer ) {
210
- $notifyer->send_message($message, $log);
211
- }
212
-
213
- $this->push_to_chrome($errorMessage);
214
- }
215
- }
216
-
217
- public function push_to_chrome($message) {
218
- $push_chrome = PostmanNotifyOptions::getInstance()->useChromeExtension();
219
-
220
- if ( $push_chrome ) {
221
- $uid = PostmanNotifyOptions::getInstance()->getNotificationChromeUid();
222
-
223
- if ( empty( $uid ) ) {
224
- return;
225
- }
226
-
227
- $url = 'https://chrome.postmansmtp.com/' . $uid;
228
-
229
- $args = array(
230
- 'body' => array(
231
- 'message' => $message
232
- )
233
- );
234
-
235
- $response = wp_remote_post( $url , $args );
236
-
237
- if ( is_wp_error( $response ) ) {
238
- error_log( 'Chrome notification error: ' . $response->get_error_message() );
239
- }
240
-
241
- if ( wp_remote_retrieve_response_code( $response ) !== 200 ) {
242
- error_log( 'Chrome notification error HTTP Error:' . wp_remote_retrieve_response_code( $response ) );
243
- }
244
- }
245
- }
246
-
247
- private function printSelectOption( $label, $optionKey, $currentKey ) {
248
- $optionPattern = '<option value="%1$s" %2$s>%3$s</option>';
249
- printf( $optionPattern, $optionKey, $optionKey == $currentKey ? 'selected="selected"' : '', $label );
250
- }
251
- }
252
- new PostmanNotify();
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ require_once 'INotify.php';
7
+ require_once 'PostmanMailNotify.php';
8
+ require_once 'PostmanPushoverNotify.php';
9
+ require_once 'PostmanSlackNotify.php';
10
+ require_once 'PostmanNotifyOptions.php';
11
+
12
+ class PostmanNotify {
13
+
14
+ const NOTIFICATIONS_OPTIONS = 'postman_notifications_options';
15
+ const NOTIFICATIONS_SECTION = 'postman_notifications_section';
16
+ const NOTIFICATIONS_PUSHOVER_CRED = 'postman_pushover_cred';
17
+ const NOTIFICATIONS_SLACK_CRED = 'postman_slack_cred';
18
+
19
+ private $options;
20
+
21
+ public function __construct() {
22
+
23
+ $this->options = PostmanNotifyOptions::getInstance();
24
+
25
+ add_filter( 'post_smtp_admin_tabs', array( $this, 'tabs' ) );
26
+ add_action( 'post_smtp_settings_menu', array( $this, 'menu' ) );
27
+ add_action( 'post_smtp_settings_fields', array( $this, 'settings' ) );
28
+ add_action( 'post_smtp_on_failed', array( $this, 'notify' ), 10, 5 );
29
+ add_filter( 'post_smtp_sanitize', array( $this, 'sanitize' ), 10, 3 );
30
+ }
31
+
32
+ public function menu() {
33
+ print '<section id="notifications">';
34
+ do_settings_sections( self::NOTIFICATIONS_OPTIONS );
35
+
36
+ $currentKey = $this->options->getNotificationService();
37
+ $pushover = $currentKey == 'pushover' ? 'block' : 'none';
38
+ $slack = $currentKey == 'slack' ? 'block' : 'none';
39
+
40
+ echo '<div id="pushover_cred" style="display: ' . $pushover . ';">';
41
+ do_settings_sections( self::NOTIFICATIONS_PUSHOVER_CRED );
42
+ echo '</div>';
43
+
44
+ echo '<div id="slack_cred" style="display: ' . $slack . ';">';
45
+ do_settings_sections( self::NOTIFICATIONS_SLACK_CRED );
46
+ echo '</div>';
47
+
48
+ do_action( 'post_smtp_notification_settings' );
49
+
50
+ print '</section>';
51
+ }
52
+
53
+ public function sanitize($new_input, $input, $sanitizer) {
54
+ // Notifications
55
+ $sanitizer->sanitizeString( 'Pushover Service', PostmanNotifyOptions::NOTIFICATION_SERVICE, $input, $new_input, $this->options->getNotificationService() );
56
+ $sanitizer->sanitizePassword( 'Pushover Username', PostmanNotifyOptions::PUSHOVER_USER, $input, $new_input, $this->options->getPushoverUser() );
57
+ $sanitizer->sanitizePassword( 'Pushover Token', PostmanNotifyOptions::PUSHOVER_TOKEN, $input, $new_input, $this->options->getPushoverToken() );
58
+ $sanitizer->sanitizePassword( 'Slack Token', PostmanNotifyOptions::SLACK_TOKEN, $input, $new_input, $this->options->getSlackToken() );
59
+
60
+ // Chrome extension
61
+ $sanitizer->sanitizeString( 'Push Chrome Extension', PostmanNotifyOptions::NOTIFICATION_USE_CHROME, $input, $new_input );
62
+ $sanitizer->sanitizePassword( 'Push Chrome Extension UID', PostmanNotifyOptions::NOTIFICATION_CHROME_UID, $input, $new_input, $this->options->getNotificationChromeUid() );
63
+
64
+ return $new_input;
65
+ }
66
+
67
+ public function tabs($tabs) {
68
+ $tabs['notifications'] = __( 'Notifications', 'post-smtp' );
69
+
70
+ return $tabs;
71
+ }
72
+
73
+ public function settings() {
74
+ // Notifications
75
+ add_settings_section( self::NOTIFICATIONS_SECTION, _x( 'Notifications Settings', 'Configuration Section Title', 'post-smtp' ), array(
76
+ $this,
77
+ 'printNotificationsSectionInfo',
78
+ ), self::NOTIFICATIONS_OPTIONS );
79
+
80
+ add_settings_field( PostmanNotifyOptions::NOTIFICATION_SERVICE, _x( 'Notification Service', 'Configuration Input Field', 'post-smtp' ), array(
81
+ $this,
82
+ 'notification_service_callback',
83
+ ), self::NOTIFICATIONS_OPTIONS, self::NOTIFICATIONS_SECTION );
84
+
85
+ // Pushover
86
+ add_settings_section( 'pushover_credentials', _x( 'Pushover Credentials', 'Configuration Section Title', 'post-smtp' ), array(
87
+ $this,
88
+ 'printNotificationsSectionInfo',
89
+ ), self::NOTIFICATIONS_PUSHOVER_CRED );
90
+
91
+ add_settings_field( PostmanNotifyOptions::PUSHOVER_USER, _x( 'Pushover User Key', 'Configuration Input Field', 'post-smtp' ), array(
92
+ $this,
93
+ 'pushover_user_callback',
94
+ ), self::NOTIFICATIONS_PUSHOVER_CRED, 'pushover_credentials' );
95
+
96
+ add_settings_field( PostmanNotifyOptions::PUSHOVER_TOKEN, _x( 'Pushover App Token', 'Configuration Input Field', 'post-smtp' ), array(
97
+ $this,
98
+ 'pushover_token_callback',
99
+ ), self::NOTIFICATIONS_PUSHOVER_CRED, 'pushover_credentials' );
100
+
101
+ // Slack
102
+ add_settings_section( 'slack_credentials', _x( 'Slack Credentials', 'Configuration Section Title', 'post-smtp' ), array(
103
+ $this,
104
+ 'printNotificationsSectionInfo',
105
+ ), self::NOTIFICATIONS_SLACK_CRED );
106
+
107
+ add_settings_field( PostmanNotifyOptions::SLACK_TOKEN, _x( 'Slack Webhook', 'Configuration Input Field', 'post-smtp' ), array(
108
+ $this,
109
+ 'slack_token_callback',
110
+ ), self::NOTIFICATIONS_SLACK_CRED, 'slack_credentials' );
111
+
112
+ add_settings_field( PostmanNotifyOptions::NOTIFICATION_USE_CHROME, _x( 'Push to chrome extension', 'Configuration Input Field', 'post-smtp' ), array(
113
+ $this,
114
+ 'notification_use_chrome_callback',
115
+ ), self::NOTIFICATIONS_OPTIONS, self::NOTIFICATIONS_SECTION );
116
+
117
+ add_settings_field( 'notification_chrome_uid', _x( 'Chrome Extension UID', 'Configuration Input Field', 'post-smtp' ), array(
118
+ $this,
119
+ 'notification_chrome_uid_callback',
120
+ ), self::NOTIFICATIONS_OPTIONS, self::NOTIFICATIONS_SECTION );
121
+ }
122
+
123
+ /**
124
+ * Print the Section text
125
+ */
126
+ public function printNotificationsSectionInfo() {
127
+ }
128
+
129
+ public function notification_service_callback() {
130
+ $inputDescription = __( 'Select the notification service you want to recieve alerts about failed emails.' );
131
+
132
+ $options = apply_filters('post_smtp_notification_service', array(
133
+ 'none' => __( 'None', 'post-smtp' ),
134
+ 'default' => __( 'WP Admin Email', 'post-smtp' ),
135
+ 'pushover' => __( 'Pushover', 'post-smtp' ),
136
+ 'slack' => __( 'Slack', 'post-smtp' ),
137
+ ));
138
+
139
+ printf( '<select id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]">', 'postman_options', PostmanNotifyOptions::NOTIFICATION_SERVICE );
140
+ $currentKey = $this->options->getNotificationService();
141
+
142
+ foreach ( $options as $key => $label ) {
143
+ $this->printSelectOption( $label, $key, $currentKey );
144
+ }
145
+
146
+ printf( '</select><br/><span class="postman_input_description">%s</span>', $inputDescription );
147
+ }
148
+
149
+ public function notification_use_chrome_callback() {
150
+ $value = $this->options->useChromeExtension();
151
+ printf( '<input type="checkbox" id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]" %3$s />', 'postman_options', PostmanNotifyOptions::NOTIFICATION_USE_CHROME, $value ? 'checked="checked"' : '' );
152
+ }
153
+
154
+ public function notification_chrome_uid_callback() {
155
+ printf( '<input type="password" id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', 'postman_options', 'notification_chrome_uid', PostmanUtils::obfuscatePassword( $this->options->getNotificationChromeUid() ) );
156
+ }
157
+
158
+ public function pushover_user_callback() {
159
+ printf( '<input type="password" id="pushover_user" name="%s[%s]" value="%s" />', 'postman_options', PostmanNotifyOptions::PUSHOVER_USER, $this->options->getPushoverUser() );
160
+ }
161
+
162
+ public function pushover_token_callback() {
163
+ printf( '<input type="password" id="pushover_token" name="%s[%s]" value="%s" />', 'postman_options', PostmanNotifyOptions::PUSHOVER_TOKEN, $this->options->getPushoverToken() );
164
+ }
165
+
166
+ public function slack_token_callback() {
167
+ printf( '<input type="password" id="slack_token" name="%s[%s]" value="%s" />', 'postman_options', PostmanNotifyOptions::SLACK_TOKEN, $this->options->getSlackToken() );
168
+ echo '<a target="_blank" href="https://slack.postmansmtp.com/">' . __( 'Get your webhook URL here', 'post-smtp' ) . '</a>';
169
+
170
+ }
171
+
172
+ /**
173
+ * @param PostmanEmailLog $log
174
+ * @param PostmanMessage $message
175
+ * @param string $transcript
176
+ * @param PostmanTransport $transport
177
+ * @param string $errorMessage
178
+ */
179
+ public function notify ($log, $postmanMessage, $transcript, $transport, $errorMessage ) {
180
+ $message = __( 'You getting this message because an error detected while delivered your email.', 'post-smtp' );
181
+ $message .= "\r\n" . sprintf( __( 'For the domain: %1$s','post-smtp' ), get_bloginfo('url') );
182
+ $message .= "\r\n" . __( 'The log to paste when you open a support issue:', 'post-smtp' ) . "\r\n";
183
+
184
+ if ( $errorMessage && ! empty( $errorMessage ) ) {
185
+
186
+ $message = $message . $errorMessage;
187
+
188
+ $notification_service = PostmanNotifyOptions::getInstance()->getNotificationService();
189
+ switch ($notification_service) {
190
+ case 'none':
191
+ $notifyer = false;
192
+ break;
193
+ case 'default':
194
+ $notifyer = new PostmanMailNotify;
195
+ break;
196
+ case 'pushover':
197
+ $notifyer = new PostmanPushoverNotify;
198
+ break;
199
+ case 'slack':
200
+ $notifyer = new PostmanSlackNotify;
201
+ break;
202
+ default:
203
+ $notifyer = new PostmanMailNotify;
204
+ }
205
+
206
+ $notifyer = apply_filters('post_smtp_notifier', $notifyer, $notification_service);
207
+
208
+ // Notifications
209
+ if ( $notifyer ) {
210
+ $notifyer->send_message($message, $log);
211
+ }
212
+
213
+ $this->push_to_chrome($errorMessage);
214
+ }
215
+ }
216
+
217
+ public function push_to_chrome($message) {
218
+ $push_chrome = PostmanNotifyOptions::getInstance()->useChromeExtension();
219
+
220
+ if ( $push_chrome ) {
221
+ $uid = PostmanNotifyOptions::getInstance()->getNotificationChromeUid();
222
+
223
+ if ( empty( $uid ) ) {
224
+ return;
225
+ }
226
+
227
+ $url = 'https://chrome.postmansmtp.com/' . $uid;
228
+
229
+ $args = array(
230
+ 'body' => array(
231
+ 'message' => $message
232
+ )
233
+ );
234
+
235
+ $response = wp_remote_post( $url , $args );
236
+
237
+ if ( is_wp_error( $response ) ) {
238
+ error_log( 'Chrome notification error: ' . $response->get_error_message() );
239
+ }
240
+
241
+ if ( wp_remote_retrieve_response_code( $response ) !== 200 ) {
242
+ error_log( 'Chrome notification error HTTP Error:' . wp_remote_retrieve_response_code( $response ) );
243
+ }
244
+ }
245
+ }
246
+
247
+ private function printSelectOption( $label, $optionKey, $currentKey ) {
248
+ $optionPattern = '<option value="%1$s" %2$s>%3$s</option>';
249
+ printf( $optionPattern, $optionKey, $optionKey == $currentKey ? 'selected="selected"' : '', $label );
250
+ }
251
+ }
252
+ new PostmanNotify();
Postman/Extensions/Core/Notifications/PostmanNotifyOptions.php CHANGED
@@ -1,68 +1,68 @@
1
- <?php
2
-
3
- class PostmanNotifyOptions {
4
-
5
- const DEFAULT_NOTIFICATION_SERVICE = 'default';
6
- const NOTIFICATION_SERVICE = 'notification_service';
7
- const NOTIFICATION_USE_CHROME = 'notification_use_chrome';
8
- const NOTIFICATION_CHROME_UID = 'notification_chrome_uid';
9
- const PUSHOVER_USER = 'pushover_user';
10
- const PUSHOVER_TOKEN = 'pushover_token';
11
- const SLACK_TOKEN = 'slack_token';
12
-
13
- private $options;
14
-
15
- private static $instance;
16
-
17
- public static function getInstance()
18
- {
19
- if ( ! self::$instance ) {
20
- self::$instance = new static;
21
- }
22
-
23
- return self::$instance;
24
- }
25
-
26
- private function __construct()
27
- {
28
- $this->options = get_option( 'postman_options' );
29
- }
30
-
31
- public function getNotificationService() {
32
- if ( isset( $this->options [ self::NOTIFICATION_SERVICE ] ) ) {
33
- return $this->options [ self::NOTIFICATION_SERVICE ];
34
- } else {
35
- return self::DEFAULT_NOTIFICATION_SERVICE;
36
- }
37
- }
38
-
39
- public function getPushoverUser() {
40
- if ( isset( $this->options [ self::PUSHOVER_USER ] ) ) {
41
- return base64_decode( $this->options [ self::PUSHOVER_USER ] );
42
- }
43
- }
44
-
45
- public function getPushoverToken() {
46
- if ( isset( $this->options [ self::PUSHOVER_TOKEN ] ) ) {
47
- return base64_decode( $this->options [ self::PUSHOVER_TOKEN ] );
48
- }
49
- }
50
-
51
- public function getSlackToken() {
52
- if ( isset( $this->options [ self::SLACK_TOKEN ] ) ) {
53
- return base64_decode( $this->options [ self::SLACK_TOKEN ] );
54
- }
55
- }
56
-
57
- public function useChromeExtension() {
58
- if ( isset( $this->options [ self::NOTIFICATION_USE_CHROME ] ) ) {
59
- return $this->options [ self::NOTIFICATION_USE_CHROME ];
60
- }
61
- }
62
-
63
- public function getNotificationChromeUid() {
64
- if ( isset( $this->options [ self::NOTIFICATION_CHROME_UID ] ) ) {
65
- return base64_decode( $this->options [ self::NOTIFICATION_CHROME_UID ] );
66
- }
67
- }
68
  }
1
+ <?php
2
+
3
+ class PostmanNotifyOptions {
4
+
5
+ const DEFAULT_NOTIFICATION_SERVICE = 'default';
6
+ const NOTIFICATION_SERVICE = 'notification_service';
7
+ const NOTIFICATION_USE_CHROME = 'notification_use_chrome';
8
+ const NOTIFICATION_CHROME_UID = 'notification_chrome_uid';
9
+ const PUSHOVER_USER = 'pushover_user';
10
+ const PUSHOVER_TOKEN = 'pushover_token';
11
+ const SLACK_TOKEN = 'slack_token';
12
+
13
+ private $options;
14
+
15
+ private static $instance;
16
+
17
+ public static function getInstance()
18
+ {
19
+ if ( ! self::$instance ) {
20
+ self::$instance = new static;
21
+ }
22
+
23
+ return self::$instance;
24
+ }
25
+
26
+ private function __construct()
27
+ {
28
+ $this->options = get_option( 'postman_options' );
29
+ }
30
+
31
+ public function getNotificationService() {
32
+ if ( isset( $this->options [ self::NOTIFICATION_SERVICE ] ) ) {
33
+ return $this->options [ self::NOTIFICATION_SERVICE ];
34
+ } else {
35
+ return self::DEFAULT_NOTIFICATION_SERVICE;
36
+ }
37
+ }
38
+
39
+ public function getPushoverUser() {
40
+ if ( isset( $this->options [ self::PUSHOVER_USER ] ) ) {
41
+ return base64_decode( $this->options [ self::PUSHOVER_USER ] );
42
+ }
43
+ }
44
+
45
+ public function getPushoverToken() {
46
+ if ( isset( $this->options [ self::PUSHOVER_TOKEN ] ) ) {
47
+ return base64_decode( $this->options [ self::PUSHOVER_TOKEN ] );
48
+ }
49
+ }
50
+
51
+ public function getSlackToken() {
52
+ if ( isset( $this->options [ self::SLACK_TOKEN ] ) ) {
53
+ return base64_decode( $this->options [ self::SLACK_TOKEN ] );
54
+ }
55
+ }
56
+
57
+ public function useChromeExtension() {
58
+ if ( isset( $this->options [ self::NOTIFICATION_USE_CHROME ] ) ) {
59
+ return $this->options [ self::NOTIFICATION_USE_CHROME ];
60
+ }
61
+ }
62
+
63
+ public function getNotificationChromeUid() {
64
+ if ( isset( $this->options [ self::NOTIFICATION_CHROME_UID ] ) ) {
65
+ return base64_decode( $this->options [ self::NOTIFICATION_CHROME_UID ] );
66
+ }
67
+ }
68
  }
Postman/Extensions/Core/Notifications/PostmanPushoverNotify.php CHANGED
@@ -1,34 +1,34 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
- class PostmanPushoverNotify implements Postman_Notify {
6
-
7
- public function send_message($message)
8
- {
9
- $options = PostmanNotifyOptions::getInstance();
10
-
11
- $api_url = "https://api.pushover.net/1/messages.json";
12
- $app_token = $options->getPushoverToken();
13
- $user_key = $options->getPushoverUser();
14
-
15
- $args = array(
16
- 'body' => array(
17
- "token" => $app_token,
18
- "user" => $user_key,
19
- "message" => $message,
20
- )
21
- );
22
-
23
- $result = wp_remote_post( $api_url, $args );
24
-
25
- if ( is_wp_error($result) ) {
26
- error_log( __CLASS__ . ': ' . $result->get_error_message() );
27
- }
28
-
29
- $body = json_decode( wp_remote_retrieve_body( $result ), true );
30
- if ( $body['status'] == 0 ) {
31
- error_log( __CLASS__ . ': ' . print_r( $body, true ) );
32
- }
33
- }
34
  }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+ class PostmanPushoverNotify implements Postman_Notify {
6
+
7
+ public function send_message($message)
8
+ {
9
+ $options = PostmanNotifyOptions::getInstance();
10
+
11
+ $api_url = "https://api.pushover.net/1/messages.json";
12
+ $app_token = $options->getPushoverToken();
13
+ $user_key = $options->getPushoverUser();
14
+
15
+ $args = array(
16
+ 'body' => array(
17
+ "token" => $app_token,
18
+ "user" => $user_key,
19
+ "message" => $message,
20
+ )
21
+ );
22
+
23
+ $result = wp_remote_post( $api_url, $args );
24
+
25
+ if ( is_wp_error($result) ) {
26
+ error_log( __CLASS__ . ': ' . $result->get_error_message() );
27
+ }
28
+
29
+ $body = json_decode( wp_remote_retrieve_body( $result ), true );
30
+ if ( $body['status'] == 0 ) {
31
+ error_log( __CLASS__ . ': ' . print_r( $body, true ) );
32
+ }
33
+ }
34
  }
Postman/Extensions/Core/Notifications/PostmanSlackNotify.php CHANGED
@@ -1,40 +1,40 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- class PostmanSlackNotify implements Postman_Notify {
7
-
8
- public function send_message($message)
9
- {
10
- $options = PostmanNotifyOptions::getInstance();
11
-
12
- $api_url = $options->getSlackToken();
13
-
14
- $headers = array(
15
- 'content-type' => 'application/json'
16
- );
17
-
18
- $body = array(
19
- 'text' => $message
20
- );
21
-
22
- $args = array(
23
- 'headers' => $headers,
24
- 'body' => json_encode($body)
25
- );
26
-
27
- $result = wp_remote_post( $api_url, $args );
28
-
29
- if ( is_wp_error($result) ) {
30
- error_log( __CLASS__ . ': ' . $result->get_error_message() );
31
- }
32
-
33
- $code = wp_remote_retrieve_response_code( $result );
34
- $message = wp_remote_retrieve_response_message( $result );
35
-
36
- if ( $code != 200 && $message !== 'OK' ) {
37
- error_log( __CLASS__ . ': ' . $message );
38
- }
39
- }
40
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ class PostmanSlackNotify implements Postman_Notify {
7
+
8
+ public function send_message($message)
9
+ {
10
+ $options = PostmanNotifyOptions::getInstance();
11
+
12
+ $api_url = $options->getSlackToken();
13
+
14
+ $headers = array(
15
+ 'content-type' => 'application/json'
16
+ );
17
+
18
+ $body = array(
19
+ 'text' => $message
20
+ );
21
+
22
+ $args = array(
23
+ 'headers' => $headers,
24
+ 'body' => json_encode($body)
25
+ );
26
+
27
+ $result = wp_remote_post( $api_url, $args );
28
+
29
+ if ( is_wp_error($result) ) {
30
+ error_log( __CLASS__ . ': ' . $result->get_error_message() );
31
+ }
32
+
33
+ $code = wp_remote_retrieve_response_code( $result );
34
+ $message = wp_remote_retrieve_response_message( $result );
35
+
36
+ if ( $code != 200 && $message !== 'OK' ) {
37
+ error_log( __CLASS__ . ': ' . $message );
38
+ }
39
+ }
40
+ }
Postman/Extensions/Core/StatusSolution.php CHANGED
@@ -1,60 +1,60 @@
1
- <?php
2
-
3
- class StatusSolution {
4
-
5
- private $status;
6
-
7
- public function __construct() {
8
- add_filter( 'post_smtp_log_solution', array( $this, 'find_solution' ), 10, 4 );
9
- }
10
-
11
- public function find_solution( $solution, $status, $log, $message ) {
12
-
13
- if ( empty( $status ) ) {
14
- return 'All good, mail sent.';
15
- }
16
-
17
- $this->status = addslashes( $status );
18
- $possible_solution = [];
19
-
20
- if ( $this->strExists('timed out') ) {
21
- $possible_solution[] = $this->make_clickable('https://postmansmtp.com/office365-smtp-connection-timed-out/');
22
- } elseif ( $this->strExists('timeout') || $this->strExists('open socket' ) ) {
23
- $possible_solution[] = 'Your hosting is blocking the connection, contact their support';
24
- } elseif ( $this->strExists( 'DATA NOT ACCEPTED' ) || $this->strExists('Exception:SendAsDeniedException' ) ) {
25
- $possible_solution[] = $this->make_clickable('https://postmansmtp.com/storedrv-submission-exceptionsendasdeniedexception-mapiexceptionsendasdenied/');
26
- } elseif ( $this->strExists( 'Incorrect authentication data') ) {
27
- $possible_solution[] = $this->make_clickable( 'https://postmansmtp.com/incorrect-authentication-data/' );
28
- } elseif ( $this->strExists( 'Unrecognized authentication type' ) ) {
29
- $possible_solution[] = 'Change "Authentication" type on plugin settings to "Login"';
30
- } elseif ( $this->strExists( 'Error executing "SendRawEmail"' ) ) {
31
- $possible_solution[] = 'Amazon SES - account permission error (review account configuration)';
32
- } elseif ( $this->strExists( 'Please log in via your web browser and then try again' ) ) {
33
- $possible_solution[] = $this->make_clickable( 'https://postmansmtp.com/gmail-gsuite-please-log-in-via-your-web-browser-and-then-try-again/' );
34
- } elseif ( $this->strExists( 'Application-specific password required' ) ) {
35
- $possible_solution[] = 'Two factor authentication is enabled, replace your password with app password.';
36
- $possible_solution[] = $this->make_clickable( 'https://support.google.com/mail/?p=InvalidSecondFactor' );
37
- } elseif ( $this->strExists( 'Username and Password not accepted' ) || $this->strExists( 'Authentication unsuccessful' ) ) {
38
- $possible_solution[] = 'Check you credentials, wrong email or password.';
39
- } elseif ( $this->strExists( 'ErrorSendAsDenied' ) ) {
40
- $possible_solution[] = 'Give the configured account "Send As" permissions on the "From" mailbox (admin.office365.com).';
41
- } elseif ( $this->strExists( 'ErrorParticipantDoesntHaveAnEmailAddress' ) ) {
42
- $possible_solution[] = "Probably office 365 doesn't like shared mailbox in Reply-To field";
43
- } else {
44
- $possible_solution[] = 'Not found, check status column for more info.';
45
- }
46
-
47
- return ! empty( $possible_solution ) ? implode( '<br>', $possible_solution ) : '';
48
- }
49
-
50
- private function make_clickable($url) {
51
- return '<a target="_blank" href="' . esc_url($url ) . '">' . esc_html( 'Read here' ) . '</a>';
52
- }
53
-
54
- private function strExists( $value ) {
55
- return strpos( strtolower( $this->status ), strtolower( addslashes( $value ) ) ) !== false;
56
- }
57
-
58
- }
59
-
60
- new StatusSolution();
1
+ <?php
2
+
3
+ class StatusSolution {
4
+
5
+ private $status;
6
+
7
+ public function __construct() {
8
+ add_filter( 'post_smtp_log_solution', array( $this, 'find_solution' ), 10, 4 );
9
+ }
10
+
11
+ public function find_solution( $solution, $status, $log, $message ) {
12
+
13
+ if ( empty( $status ) ) {
14
+ return 'All good, mail sent.';
15
+ }
16
+
17
+ $this->status = addslashes( $status );
18
+ $possible_solution = [];
19
+
20
+ if ( $this->strExists('timed out') ) {
21
+ $possible_solution[] = $this->make_clickable('https://postmansmtp.com/office365-smtp-connection-timed-out/');
22
+ } elseif ( $this->strExists('timeout') || $this->strExists('open socket' ) ) {
23
+ $possible_solution[] = 'Your hosting is blocking the connection, contact their support';
24
+ } elseif ( $this->strExists( 'DATA NOT ACCEPTED' ) || $this->strExists('Exception:SendAsDeniedException' ) ) {
25
+ $possible_solution[] = $this->make_clickable('https://postmansmtp.com/storedrv-submission-exceptionsendasdeniedexception-mapiexceptionsendasdenied/');
26
+ } elseif ( $this->strExists( 'Incorrect authentication data') ) {
27
+ $possible_solution[] = $this->make_clickable( 'https://postmansmtp.com/incorrect-authentication-data/' );
28
+ } elseif ( $this->strExists( 'Unrecognized authentication type' ) ) {
29
+ $possible_solution[] = 'Change "Authentication" type on plugin settings to "Login"';
30
+ } elseif ( $this->strExists( 'Error executing "SendRawEmail"' ) ) {
31
+ $possible_solution[] = 'Amazon SES - account permission error (review account configuration)';
32
+ } elseif ( $this->strExists( 'Please log in via your web browser and then try again' ) ) {
33
+ $possible_solution[] = $this->make_clickable( 'https://postmansmtp.com/gmail-gsuite-please-log-in-via-your-web-browser-and-then-try-again/' );
34
+ } elseif ( $this->strExists( 'Application-specific password required' ) ) {
35
+ $possible_solution[] = 'Two factor authentication is enabled, replace your password with app password.';
36
+ $possible_solution[] = $this->make_clickable( 'https://support.google.com/mail/?p=InvalidSecondFactor' );
37
+ } elseif ( $this->strExists( 'Username and Password not accepted' ) || $this->strExists( 'Authentication unsuccessful' ) ) {
38
+ $possible_solution[] = 'Check you credentials, wrong email or password.';
39
+ } elseif ( $this->strExists( 'ErrorSendAsDenied' ) ) {
40
+ $possible_solution[] = 'Give the configured account "Send As" permissions on the "From" mailbox (admin.office365.com).';
41
+ } elseif ( $this->strExists( 'ErrorParticipantDoesntHaveAnEmailAddress' ) ) {
42
+ $possible_solution[] = "Probably office 365 doesn't like shared mailbox in Reply-To field";
43
+ } else {
44
+ $possible_solution[] = 'Not found, check status column for more info.';
45
+ }
46
+
47
+ return ! empty( $possible_solution ) ? implode( '<br>', $possible_solution ) : '';
48
+ }
49
+
50
+ private function make_clickable($url) {
51
+ return '<a target="_blank" href="' . esc_url($url ) . '">' . esc_html( 'Read here' ) . '</a>';
52
+ }
53
+
54
+ private function strExists( $value ) {
55
+ return strpos( strtolower( $this->status ), strtolower( addslashes( $value ) ) ) !== false;
56
+ }
57
+
58
+ }
59
+
60
+ new StatusSolution();
Postman/Localize.php CHANGED
@@ -1,29 +1,29 @@
1
- <?php
2
- $warning = __( 'Warning', 'post-smtp' );
3
-
4
- return array(
5
- /* translators: where %s is the name of the SMTP server */
6
- 'postman_smtp_mitm' => sprintf( '%s: %s', $warning, __( 'connected to %1$s instead of %2$s.', 'post-smtp' ) ),
7
- /* translators: where %d is a port number */
8
- 'postman_wizard_bad_redirect_url' => __( 'You are about to configure OAuth 2.0 with an IP address instead of a domain name. This is not permitted. Either assign a real domain name to your site or add a fake one in your local host file.', 'post-smtp' ),
9
- 'postman_input_sender_email' => '#input_' . PostmanOptions::MESSAGE_SENDER_EMAIL,
10
- 'postman_input_sender_name' => '#input_' . PostmanOptions::MESSAGE_SENDER_NAME,
11
- 'postman_port_element_name' => '#input_' . PostmanOptions::PORT,
12
- 'postman_hostname_element_name' => '#input_' . PostmanOptions::HOSTNAME,
13
- 'postman_enc_for_password_el' => '#input_enc_type_password',
14
- 'postman_input_basic_username' => '#input_' . PostmanOptions::BASIC_AUTH_USERNAME,
15
- 'postman_input_basic_password' => '#input_' . PostmanOptions::BASIC_AUTH_PASSWORD,
16
- 'postman_redirect_url_el' => '#input_oauth_redirect_url',
17
- 'postman_input_auth_type' => '#input_' . PostmanOptions::AUTHENTICATION_TYPE,
18
- 'postman_js_email_was_resent' => __( 'Email was successfully resent (but without attachments)', 'post-smtp' ),
19
- /* Translators: Where %s is an error message */
20
- 'postman_js_email_not_resent' => __( 'Email could not be resent. Error: %s', 'post-smtp' ),
21
- 'postman_js_resend_label' => __( 'Resend', 'post-smtp' ),
22
- 'steps_current_step' => 'steps_current_step',
23
- 'steps_pagination' => 'steps_pagination',
24
- 'steps_finish' => _x( 'Finish', 'Press this button to Finish this task', 'post-smtp' ),
25
- 'steps_next' => _x( 'Next', 'Press this button to go to the next step', 'post-smtp' ),
26
- 'steps_previous' => _x( 'Previous', 'Press this button to go to the previous step', 'post-smtp' ),
27
- 'steps_loading' => 'steps_loading'
28
- );
29
-
1
+ <?php
2
+ $warning = __( 'Warning', 'post-smtp' );
3
+
4
+ return array(
5
+ /* translators: where %s is the name of the SMTP server */
6
+ 'postman_smtp_mitm' => sprintf( '%s: %s', $warning, __( 'connected to %1$s instead of %2$s.', 'post-smtp' ) ),
7
+ /* translators: where %d is a port number */
8
+ 'postman_wizard_bad_redirect_url' => __( 'You are about to configure OAuth 2.0 with an IP address instead of a domain name. This is not permitted. Either assign a real domain name to your site or add a fake one in your local host file.', 'post-smtp' ),
9
+ 'postman_input_sender_email' => '#input_' . PostmanOptions::MESSAGE_SENDER_EMAIL,
10
+ 'postman_input_sender_name' => '#input_' . PostmanOptions::MESSAGE_SENDER_NAME,
11
+ 'postman_port_element_name' => '#input_' . PostmanOptions::PORT,
12
+ 'postman_hostname_element_name' => '#input_' . PostmanOptions::HOSTNAME,
13
+ 'postman_enc_for_password_el' => '#input_enc_type_password',
14
+ 'postman_input_basic_username' => '#input_' . PostmanOptions::BASIC_AUTH_USERNAME,
15
+ 'postman_input_basic_password' => '#input_' . PostmanOptions::BASIC_AUTH_PASSWORD,
16
+ 'postman_redirect_url_el' => '#input_oauth_redirect_url',
17
+ 'postman_input_auth_type' => '#input_' . PostmanOptions::AUTHENTICATION_TYPE,
18
+ 'postman_js_email_was_resent' => __( 'Email was successfully resent (but without attachments)', 'post-smtp' ),
19
+ /* Translators: Where %s is an error message */
20
+ 'postman_js_email_not_resent' => __( 'Email could not be resent. Error: %s', 'post-smtp' ),
21
+ 'postman_js_resend_label' => __( 'Resend', 'post-smtp' ),
22
+ 'steps_current_step' => 'steps_current_step',
23
+ 'steps_pagination' => 'steps_pagination',
24
+ 'steps_finish' => _x( 'Finish', 'Press this button to Finish this task', 'post-smtp' ),
25
+ 'steps_next' => _x( 'Next', 'Press this button to go to the next step', 'post-smtp' ),
26
+ 'steps_previous' => _x( 'Previous', 'Press this button to go to the previous step', 'post-smtp' ),
27
+ 'steps_loading' => 'steps_loading'
28
+ );
29
+
Postman/Phpmailer/PostsmtpMailer.php CHANGED
@@ -1,174 +1,174 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- if ( version_compare( get_bloginfo( 'version' ), '5.5-alpha', '<' ) ) {
7
- if ( ! class_exists( '\PHPMailer', false ) ) {
8
- require_once ABSPATH . WPINC . '/class-phpmailer.php';
9
- }
10
-
11
- } else {
12
- if ( ! class_exists( '\PHPMailer\PHPMailer\PHPMailer', false ) ) {
13
- require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php';
14
- }
15
-
16
- if ( ! class_exists( '\PHPMailer\PHPMailer\Exception', false ) ) {
17
- require_once ABSPATH . WPINC . '/PHPMailer/Exception.php';
18
- }
19
-
20
- if ( ! class_exists( '\PHPMailer\PHPMailer\SMTP', false ) ) {
21
- require_once ABSPATH . WPINC . '/PHPMailer/SMTP.php';
22
- }
23
-
24
- class_alias( PHPMailer\PHPMailer\PHPMailer::class, 'PHPMailer' );
25
- class_alias( PHPMailer\PHPMailer\SMTP::class, 'SMTP' );
26
- class_alias( PHPMailer\PHPMailer\Exception::class, 'phpmailerException' );
27
- }
28
-
29
-
30
- add_action('plugins_loaded', function() {
31
- global $phpmailer;
32
-
33
- $phpmailer = new PostsmtpMailer(true);
34
- });
35
-
36
- class PostsmtpMailer extends PHPMailer {
37
-
38
- private $mail_args = array();
39
-
40
- private $options;
41
-
42
- private $error;
43
-
44
- private $transcript = '';
45
-
46
- public function __construct($exceptions = null)
47
- {
48
- parent::__construct($exceptions);
49
-
50
- $this->set_vars();
51
- $this->hooks();
52
-
53
- }
54
-
55
- public function set_vars() {
56
- $this->options = PostmanOptions::getInstance();
57
- $this->Debugoutput = function($str, $level) {
58
- $this->transcript .= $str;
59
- };
60
- }
61
-
62
- public function hooks() {
63
- add_filter( 'wp_mail', array( $this, 'get_mail_args' ) );
64
- if ( $this->options->getTransportType() == 'smtp' ) {
65
- add_action( 'phpmailer_init', array( $this, 'phpmailer_smtp_init' ), 999 );
66
- }
67
- }
68
-
69
- public function get_mail_args( $atts ) {
70
- $this->mail_args = array();
71
- $this->mail_args[] = @$atts['to'];
72
- $this->mail_args[] = @$atts['subject'];
73
- $this->mail_args[] = @$atts['message'];
74
- $this->mail_args[] = @$atts['headers'];
75
- $this->mail_args[] = @$atts['attachments'];
76
-
77
- return $atts;
78
- }
79
-
80
- /**
81
- * @param PHPMailer $mail
82
- */
83
- public function phpmailer_smtp_init($mail) {
84
- $mail->SMTPDebug = 3;
85
- $mail->isSMTP();
86
- $mail->Host = $this->options->getHostname();
87
-
88
- if ( $this->options->getAuthenticationType() !== 'none' ) {
89
- $mail->SMTPAuth = true;
90
- $mail->Username = $this->options->getUsername();
91
- $mail->Password = $this->options->getPassword();
92
- }
93
-
94
- if ( $this->options->getEncryptionType() !== 'none' ) {
95
- $mail->SMTPSecure = $this->options->getEncryptionType();
96
- }
97
-
98
- $mail->Port = $this->options->getPort();
99
-
100
- if ( $this->options->isPluginSenderEmailEnforced() ) {
101
- $mail->setFrom( $this->options->getMessageSenderEmail() , $this->options->getMessageSenderName () );
102
- }
103
- }
104
-
105
- public function send()
106
- {
107
- require_once dirname(__DIR__) . '/PostmanWpMail.php';
108
-
109
- // create a PostmanWpMail instance
110
- $postmanWpMail = new PostmanWpMail();
111
- $postmanWpMail->init();
112
-
113
- list($to, $subject, $body, $headers, $attachments) = array_pad( $this->mail_args, 5, null );
114
-
115
- // build the message
116
- $postmanMessage = $postmanWpMail->processWpMailCall( $to, $subject, $body, $headers, $attachments );
117
-
118
- // build the email log entry
119
- $log = new PostmanEmailLog();
120
- $log->originalTo = $to;
121
- $log->originalSubject = $subject;
122
- $log->originalMessage = $body;
123
- $log->originalHeaders = $headers;
124
-
125
- // get the transport and create the transportConfig and engine
126
- $transport = PostmanTransportRegistry::getInstance()->getActiveTransport();
127
-
128
- add_filter( 'postman_wp_mail_result', [ $this, 'postman_wp_mail_result' ] );
129
-
130
- try {
131
-
132
- if ( $send_email = apply_filters( 'post_smtp_do_send_email', true ) ) {
133
- $result = $this->options->getTransportType() !== 'smtp' ?
134
- $postmanWpMail->send( $to, $subject, $body, $headers, $attachments ) :
135
- $this->sendSmtp();
136
- }
137
-
138
-
139
- do_action( 'post_smtp_on_success', $log, $postmanMessage, $this->transcript, $transport );
140
-
141
- return $result;
142
-
143
- } catch (Exception $exc) {
144
-
145
- $this->error = $exc;
146
-
147
- $this->mailHeader = '';
148
-
149
- $this->setError($exc->getMessage());
150
- if ($this->exceptions) {
151
- throw $exc;
152
- }
153
- return false;
154
- }
155
-
156
- }
157
-
158
- public function sendSmtp() {
159
- if (!$this->preSend()) {
160
- return false;
161
- }
162
- return $this->postSend();
163
- }
164
-
165
-
166
- public function postman_wp_mail_result() {
167
- $result = [
168
- 'time' => '',
169
- 'exception' => $this->error,
170
- 'transcript' => $this->transcript,
171
- ];
172
- return $result;
173
- }
174
  }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ if ( version_compare( get_bloginfo( 'version' ), '5.5-alpha', '<' ) ) {
7
+ if ( ! class_exists( '\PHPMailer', false ) ) {
8
+ require_once ABSPATH . WPINC . '/class-phpmailer.php';
9
+ }
10
+
11
+ } else {
12
+ if ( ! class_exists( '\PHPMailer\PHPMailer\PHPMailer', false ) ) {
13
+ require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php';
14
+ }
15
+
16
+ if ( ! class_exists( '\PHPMailer\PHPMailer\Exception', false ) ) {
17
+ require_once ABSPATH . WPINC . '/PHPMailer/Exception.php';
18
+ }
19
+
20
+ if ( ! class_exists( '\PHPMailer\PHPMailer\SMTP', false ) ) {
21
+ require_once ABSPATH . WPINC . '/PHPMailer/SMTP.php';
22
+ }
23
+
24
+ class_alias( PHPMailer\PHPMailer\PHPMailer::class, 'PHPMailer' );
25
+ class_alias( PHPMailer\PHPMailer\SMTP::class, 'SMTP' );
26
+ class_alias( PHPMailer\PHPMailer\Exception::class, 'phpmailerException' );
27
+ }
28
+
29
+
30
+ add_action('plugins_loaded', function() {
31
+ global $phpmailer;
32
+
33
+ $phpmailer = new PostsmtpMailer(true);
34
+ });
35
+
36
+ class PostsmtpMailer extends PHPMailer {
37
+
38
+ private $mail_args = array();
39
+
40
+ private $options;
41
+
42
+ private $error;
43
+
44
+ private $transcript = '';
45
+
46
+ public function __construct($exceptions = null)
47
+ {
48
+ parent::__construct($exceptions);
49
+
50
+ $this->set_vars();
51
+ $this->hooks();
52
+
53
+ }
54
+
55
+ public function set_vars() {
56
+ $this->options = PostmanOptions::getInstance();
57
+ $this->Debugoutput = function($str, $level) {
58
+ $this->transcript .= $str;
59
+ };
60
+ }
61
+
62
+ public function hooks() {
63
+ add_filter( 'wp_mail', array( $this, 'get_mail_args' ) );
64
+ if ( $this->options->getTransportType() == 'smtp' ) {
65
+ add_action( 'phpmailer_init', array( $this, 'phpmailer_smtp_init' ), 999 );
66
+ }
67
+ }
68
+
69
+ public function get_mail_args( $atts ) {
70
+ $this->mail_args = array();
71
+ $this->mail_args[] = @$atts['to'];
72
+ $this->mail_args[] = @$atts['subject'];
73
+ $this->mail_args[] = @$atts['message'];
74
+ $this->mail_args[] = @$atts['headers'];
75
+ $this->mail_args[] = @$atts['attachments'];
76
+
77
+ return $atts;
78
+ }
79
+
80
+ /**
81
+ * @param PHPMailer $mail
82
+ */
83
+ public function phpmailer_smtp_init($mail) {
84
+ $mail->SMTPDebug = 3;
85
+ $mail->isSMTP();
86
+ $mail->Host = $this->options->getHostname();
87
+
88
+ if ( $this->options->getAuthenticationType() !== 'none' ) {
89
+ $mail->SMTPAuth = true;
90
+ $mail->Username = $this->options->getUsername();
91
+ $mail->Password = $this->options->getPassword();
92
+ }
93
+
94
+ if ( $this->options->getEncryptionType() !== 'none' ) {
95
+ $mail->SMTPSecure = $this->options->getEncryptionType();
96
+ }
97
+
98
+ $mail->Port = $this->options->getPort();
99
+
100
+ if ( $this->options->isPluginSenderEmailEnforced() ) {
101
+ $mail->setFrom( $this->options->getMessageSenderEmail() , $this->options->getMessageSenderName () );
102
+ }
103
+ }
104
+
105
+ public function send()
106
+ {
107
+ require_once dirname(__DIR__) . '/PostmanWpMail.php';
108
+
109
+ // create a PostmanWpMail instance
110
+ $postmanWpMail = new PostmanWpMail();
111
+ $postmanWpMail->init();
112
+
113
+ list($to, $subject, $body, $headers, $attachments) = array_pad( $this->mail_args, 5, null );
114
+
115
+ // build the message
116
+ $postmanMessage = $postmanWpMail->processWpMailCall( $to, $subject, $body, $headers, $attachments );
117
+
118
+ // build the email log entry
119
+ $log = new PostmanEmailLog();
120
+ $log->originalTo = $to;
121
+ $log->originalSubject = $subject;
122
+ $log->originalMessage = $body;
123
+ $log->originalHeaders = $headers;
124
+
125
+ // get the transport and create the transportConfig and engine
126
+ $transport = PostmanTransportRegistry::getInstance()->getActiveTransport();
127
+
128
+ add_filter( 'postman_wp_mail_result', [ $this, 'postman_wp_mail_result' ] );
129
+
130
+ try {
131
+
132
+ if ( $send_email = apply_filters( 'post_smtp_do_send_email', true ) ) {
133
+ $result = $this->options->getTransportType() !== 'smtp' ?
134
+ $postmanWpMail->send( $to, $subject, $body, $headers, $attachments ) :
135
+ $this->sendSmtp();
136
+ }
137
+
138
+
139
+ do_action( 'post_smtp_on_success', $log, $postmanMessage, $this->transcript, $transport );
140
+
141
+ return $result;
142
+
143
+ } catch (Exception $exc) {
144
+
145
+ $this->error = $exc;
146
+
147
+ $this->mailHeader = '';
148
+
149
+ $this->setError($exc->getMessage());
150
+ if ($this->exceptions) {
151
+ throw $exc;
152
+ }
153
+ return false;
154
+ }
155
+
156
+ }
157
+
158
+ public function sendSmtp() {
159
+ if (!$this->preSend()) {
160
+ return false;
161
+ }
162
+ return $this->postSend();
163
+ }
164
+
165
+
166
+ public function postman_wp_mail_result() {
167
+ $result = [
168
+ 'time' => '',
169
+ 'exception' => $this->error,
170
+ 'transcript' => $this->transcript,
171
+ ];
172
+ return $result;
173
+ }
174
  }
Postman/Postman-Auth/PostmanAbstractAuthenticationManager.php CHANGED
@@ -1,171 +1,171 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
- if (! class_exists ( "PostmanAbstractAuthenticationManager" )) {
6
-
7
- require_once 'PostmanAuthenticationManager.php';
8
-
9
- /**
10
- */
11
- abstract class PostmanAbstractAuthenticationManager implements PostmanAuthenticationManager {
12
-
13
- // constants
14
- const APPROVAL_PROMPT = 'force';
15
- const ACCESS_TYPE = 'offline';
16
- const ACCESS_TOKEN = 'access_token';
17
- const REFRESH_TOKEN = 'refresh_token';
18
- const EXPIRES = 'expires_in';
19
-
20
- // the oauth authorization options
21
- private $clientId;
22
- private $clientSecret;
23
- private $authorizationToken;
24
- private $callbackUri;
25
- private $logger;
26
-
27
- /**
28
- * Constructor
29
- */
30
- public function __construct(PostmanLogger $logger, $clientId, $clientSecret, PostmanOAuthToken $authorizationToken, $callbackUri) {
31
- assert ( ! empty ( $clientId ) );
32
- assert ( ! empty ( $clientSecret ) );
33
- assert ( ! empty ( $authorizationToken ) );
34
- assert ( ! empty ( $callbackUri ) );
35
- $this->logger = $logger;
36
- $this->clientId = $clientId;
37
- $this->clientSecret = $clientSecret;
38
- $this->authorizationToken = $authorizationToken;
39
- $this->callbackUri = $callbackUri;
40
- }
41
- protected function getLogger() {
42
- return $this->logger;
43
- }
44
- protected function getClientId() {
45
- return $this->clientId;
46
- }
47
- protected function getClientSecret() {
48
- return $this->clientSecret;
49
- }
50
- protected function getAuthorizationToken() {
51
- return $this->authorizationToken;
52
- }
53
-
54
- /**
55
- * Create a state token to prevent request forgery.
56
- * Store it in the session for later validation.
57
- */
58
- public function generateRequestTransactionId() {
59
- return $state = md5 ( rand () );
60
- }
61
-
62
- /**
63
- */
64
- public function isAccessTokenExpired() {
65
- $expireTime = ($this->authorizationToken->getExpiryTime () - self::FORCE_REFRESH_X_SECONDS_BEFORE_EXPIRE);
66
- $tokenHasExpired = time () > $expireTime;
67
- $this->logger->debug ( 'Access Token Expiry Time is ' . $expireTime . ', expires_in=' . ($expireTime - time ()) . ', expired=' . ($tokenHasExpired ? 'yes' : 'no') );
68
- return $tokenHasExpired;
69
- }
70
-
71
- /**
72
- * Decoded the received token
73
- * This code is identical for Google and Hotmail
74
- *
75
- * @param mixed $response
76
- * @throws Exception
77
- */
78
- protected function processResponse($response) {
79
- $authToken = json_decode ( stripslashes ( $response ) );
80
- if ($authToken === NULL) {
81
- $this->getLogger ()->error ( $response );
82
- throw new Exception ( $response );
83
- } else if (isset ( $authToken->{'error'} )) {
84
- if (isset ( $authToken->{'error_description'} )) {
85
- $this->getLogger ()->error ( $authToken->{'error'} . ' processing response: ' . $authToken->{'error_description'} );
86
- throw new Exception ( $authToken->{'error_description'} . '(' . $authToken->{'error'} . ')' );
87
- } else {
88
- // Yahoo doesn't give descriptions
89
- $this->getLogger ()->error ( $authToken->{'error'} . ' processing response' );
90
- throw new Exception ( $authToken->{'error'} );
91
- }
92
- } else {
93
- $this->getLogger ()->trace ( 'Processing response:' );
94
- $this->getLogger ()->trace ( $response );
95
- $this->decodeReceivedAuthorizationToken ( $authToken );
96
- }
97
- }
98
-
99
- /**
100
- * Parses the authorization token and extracts the expiry time, accessToken,
101
- * and if this is a first-time authorization, a refresh token.
102
- *
103
- * This code is identical for Google and Hotmail
104
- *
105
- * @param mixed $client
106
- */
107
- protected function decodeReceivedAuthorizationToken($newtoken) {
108
- assert ( ! empty ( $newtoken ) );
109
- assert ( ! empty ( $newtoken->{self::EXPIRES} ) );
110
- assert ( ! empty ( $newtoken->{self::ACCESS_TOKEN} ) );
111
-
112
- // update expiry time
113
- if (empty ( $newtoken->{self::EXPIRES} )) {
114
- throw new Exception ( '[expires_in] value is missing from the authentication token' );
115
- }
116
- $newExpiryTime = time () + $newtoken->{self::EXPIRES};
117
- $this->getAuthorizationToken ()->setExpiryTime ( $newExpiryTime );
118
- $this->getLogger ()->debug ( 'Updating Access Token Expiry Time ' );
119
-
120
- // update acccess token
121
- if (empty ( $newtoken->{self::ACCESS_TOKEN} )) {
122
- throw new Exception ( '[access_token] value is missing from the authentication token' );
123
- }
124
- $newAccessToken = $newtoken->{self::ACCESS_TOKEN};
125
- $this->getAuthorizationToken ()->setAccessToken ( $newAccessToken );
126
- $this->getLogger ()->debug ( 'Updating Access Token' );
127
-
128
- // update refresh token, if there is one
129
- if (isset ( $newtoken->{self::REFRESH_TOKEN} )) {
130
- $newRefreshToken = $newtoken->{self::REFRESH_TOKEN};
131
- $this->getAuthorizationToken ()->setRefreshToken ( $newRefreshToken );
132
- $this->getLogger ()->debug ( 'Updating Refresh Token ' );
133
- }
134
- }
135
-
136
- /**
137
- * Given an OAuth provider-specific URL and redirectUri,
138
- * issue an HttpRequest to refresh the access token
139
- *
140
- * This code is identical for Google and Hotmail
141
- */
142
- public function refreshToken() {
143
- $this->getLogger ()->debug ( 'Refreshing Token' );
144
- $refreshUrl = $this->getTokenUrl ();
145
- $callbackUrl = $this->getCallbackUri ();
146
- assert ( ! empty ( $refreshUrl ) );
147
- assert ( ! empty ( $callbackUrl ) );
148
- // the format of the URL is
149
- // client_id=CLIENT_ID&client_secret=CLIENT_SECRET&redirect_uri=REDIRECT_URI&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
150
- $postvals = array (
151
- 'client_id' => $this->getClientId (),
152
- 'client_secret' => $this->getClientSecret (),
153
- 'redirect_uri' => $callbackUrl,
154
- 'grant_type' => 'refresh_token',
155
- 'refresh_token' => $this->getAuthorizationToken ()->getRefreshToken ()
156
- );
157
- // example request string
158
- // client_id=0000000603DB0F&redirect_uri=http%3A%2F%2Fwww.contoso.com%2Fcallback.php&client_secret=LWILlT555GicSrIATma5qgyBXebRI&refresh_token=*LA9...//refresh token string shortened for example//...xRoX&grant_type=refresh_token
159
- $response = PostmanUtils::remotePostGetBodyOnly ( $refreshUrl, $postvals );
160
- $this->processResponse ( $response );
161
- }
162
- /**
163
- * (non-PHPdoc)
164
- *
165
- * @see PostmanAuthenticationManager::getCallbackUri()
166
- */
167
- public function getCallbackUri() {
168
- return $this->callbackUri;
169
- }
170
- }
171
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+ if (! class_exists ( "PostmanAbstractAuthenticationManager" )) {
6
+
7
+ require_once 'PostmanAuthenticationManager.php';
8
+
9
+ /**
10
+ */
11
+ abstract class PostmanAbstractAuthenticationManager implements PostmanAuthenticationManager {
12
+
13
+ // constants
14
+ const APPROVAL_PROMPT = 'force';
15
+ const ACCESS_TYPE = 'offline';
16
+ const ACCESS_TOKEN = 'access_token';
17
+ const REFRESH_TOKEN = 'refresh_token';
18
+ const EXPIRES = 'expires_in';
19
+
20
+ // the oauth authorization options
21
+ private $clientId;
22
+ private $clientSecret;
23
+ private $authorizationToken;
24
+ private $callbackUri;
25
+ private $logger;
26
+
27
+ /**
28
+ * Constructor
29
+ */
30
+ public function __construct(PostmanLogger $logger, $clientId, $clientSecret, PostmanOAuthToken $authorizationToken, $callbackUri) {
31
+ assert ( ! empty ( $clientId ) );
32
+ assert ( ! empty ( $clientSecret ) );
33
+ assert ( ! empty ( $authorizationToken ) );
34
+ assert ( ! empty ( $callbackUri ) );
35
+ $this->logger = $logger;
36
+ $this->clientId = $clientId;
37
+ $this->clientSecret = $clientSecret;
38
+ $this->authorizationToken = $authorizationToken;
39
+ $this->callbackUri = $callbackUri;
40
+ }
41
+ protected function getLogger() {
42
+ return $this->logger;
43
+ }
44
+ protected function getClientId() {
45
+ return $this->clientId;
46
+ }
47
+ protected function getClientSecret() {
48
+ return $this->clientSecret;
49
+ }
50
+ protected function getAuthorizationToken() {
51
+ return $this->authorizationToken;
52
+ }
53
+
54
+ /**
55
+ * Create a state token to prevent request forgery.
56
+ * Store it in the session for later validation.
57
+ */
58
+ public function generateRequestTransactionId() {
59
+ return $state = md5 ( rand () );
60
+ }
61
+
62
+ /**
63
+ */
64
+ public function isAccessTokenExpired() {
65
+ $expireTime = ($this->authorizationToken->getExpiryTime () - self::FORCE_REFRESH_X_SECONDS_BEFORE_EXPIRE);
66
+ $tokenHasExpired = time () > $expireTime;
67
+ $this->logger->debug ( 'Access Token Expiry Time is ' . $expireTime . ', expires_in=' . ($expireTime - time ()) . ', expired=' . ($tokenHasExpired ? 'yes' : 'no') );
68
+ return $tokenHasExpired;
69
+ }
70
+
71
+ /**
72
+ * Decoded the received token
73
+ * This code is identical for Google and Hotmail
74
+ *
75
+ * @param mixed $response
76
+ * @throws Exception
77
+ */
78
+ protected function processResponse($response) {
79
+ $authToken = json_decode ( stripslashes ( $response ) );
80
+ if ($authToken === NULL) {
81
+ $this->getLogger ()->error ( $response );
82
+ throw new Exception ( $response );
83
+ } else if (isset ( $authToken->{'error'} )) {
84
+ if (isset ( $authToken->{'error_description'} )) {
85
+ $this->getLogger ()->error ( $authToken->{'error'} . ' processing response: ' . $authToken->{'error_description'} );
86
+ throw new Exception ( $authToken->{'error_description'} . '(' . $authToken->{'error'} . ')' );
87
+ } else {
88
+ // Yahoo doesn't give descriptions
89
+ $this->getLogger ()->error ( $authToken->{'error'} . ' processing response' );
90
+ throw new Exception ( $authToken->{'error'} );
91
+ }
92
+ } else {
93
+ $this->getLogger ()->trace ( 'Processing response:' );
94
+ $this->getLogger ()->trace ( $response );
95
+ $this->decodeReceivedAuthorizationToken ( $authToken );
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Parses the authorization token and extracts the expiry time, accessToken,
101
+ * and if this is a first-time authorization, a refresh token.
102
+ *
103
+ * This code is identical for Google and Hotmail
104
+ *
105
+ * @param mixed $client
106
+ */
107
+ protected function decodeReceivedAuthorizationToken($newtoken) {
108
+ assert ( ! empty ( $newtoken ) );
109
+ assert ( ! empty ( $newtoken->{self::EXPIRES} ) );
110
+ assert ( ! empty ( $newtoken->{self::ACCESS_TOKEN} ) );
111
+
112
+ // update expiry time
113
+ if (empty ( $newtoken->{self::EXPIRES} )) {
114
+ throw new Exception ( '[expires_in] value is missing from the authentication token' );
115
+ }
116
+ $newExpiryTime = time () + $newtoken->{self::EXPIRES};
117
+ $this->getAuthorizationToken ()->setExpiryTime ( $newExpiryTime );
118
+ $this->getLogger ()->debug ( 'Updating Access Token Expiry Time ' );
119
+
120
+ // update acccess token
121
+ if (empty ( $newtoken->{self::ACCESS_TOKEN} )) {
122
+ throw new Exception ( '[access_token] value is missing from the authentication token' );
123
+ }
124
+ $newAccessToken = $newtoken->{self::ACCESS_TOKEN};
125
+ $this->getAuthorizationToken ()->setAccessToken ( $newAccessToken );
126
+ $this->getLogger ()->debug ( 'Updating Access Token' );
127
+
128
+ // update refresh token, if there is one
129
+ if (isset ( $newtoken->{self::REFRESH_TOKEN} )) {
130
+ $newRefreshToken = $newtoken->{self::REFRESH_TOKEN};
131
+ $this->getAuthorizationToken ()->setRefreshToken ( $newRefreshToken );
132
+ $this->getLogger ()->debug ( 'Updating Refresh Token ' );
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Given an OAuth provider-specific URL and redirectUri,
138
+ * issue an HttpRequest to refresh the access token
139
+ *
140
+ * This code is identical for Google and Hotmail
141
+ */
142
+ public function refreshToken() {
143
+ $this->getLogger ()->debug ( 'Refreshing Token' );
144
+ $refreshUrl = $this->getTokenUrl ();
145
+ $callbackUrl = $this->getCallbackUri ();
146
+ assert ( ! empty ( $refreshUrl ) );
147
+ assert ( ! empty ( $callbackUrl ) );
148
+ // the format of the URL is
149
+ // client_id=CLIENT_ID&client_secret=CLIENT_SECRET&redirect_uri=REDIRECT_URI&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
150
+ $postvals = array (
151
+ 'client_id' => $this->getClientId (),
152
+ 'client_secret' => $this->getClientSecret (),
153
+ 'redirect_uri' => $callbackUrl,
154
+ 'grant_type' => 'refresh_token',
155
+ 'refresh_token' => $this->getAuthorizationToken ()->getRefreshToken ()
156
+ );
157
+ // example request string
158
+ // client_id=0000000603DB0F&redirect_uri=http%3A%2F%2Fwww.contoso.com%2Fcallback.php&client_secret=LWILlT555GicSrIATma5qgyBXebRI&refresh_token=*LA9...//refresh token string shortened for example//...xRoX&grant_type=refresh_token
159
+ $response = PostmanUtils::remotePostGetBodyOnly ( $refreshUrl, $postvals );
160
+ $this->processResponse ( $response );
161
+ }
162
+ /**
163
+ * (non-PHPdoc)
164
+ *
165
+ * @see PostmanAuthenticationManager::getCallbackUri()
166
+ */
167
+ public function getCallbackUri() {
168
+ return $this->callbackUri;
169
+ }
170
+ }
171
+ }
Postman/Postman-Auth/PostmanAuthenticationManager.php CHANGED
@@ -1,18 +1,18 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
- if (! interface_exists ( "PostmanAuthenticationManager" )) {
6
- interface PostmanAuthenticationManager {
7
- const POSTMAN_AUTHORIZATION_IN_PROGRESS = 'request_oauth_permission';
8
- const FORCE_REFRESH_X_SECONDS_BEFORE_EXPIRE = 60;
9
- public function isAccessTokenExpired();
10
- public function refreshToken();
11
- public function generateRequestTransactionId();
12
- public function requestVerificationCode($transactionId);
13
- public function processAuthorizationGrantCode($transactionId);
14
- public function getAuthorizationUrl();
15
- public function getTokenUrl();
16
- public function getCallbackUri();
17
- }
18
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+ if (! interface_exists ( "PostmanAuthenticationManager" )) {
6
+ interface PostmanAuthenticationManager {
7
+ const POSTMAN_AUTHORIZATION_IN_PROGRESS = 'request_oauth_permission';
8
+ const FORCE_REFRESH_X_SECONDS_BEFORE_EXPIRE = 60;
9
+ public function isAccessTokenExpired();
10
+ public function refreshToken();
11
+ public function generateRequestTransactionId();
12
+ public function requestVerificationCode($transactionId);
13
+ public function processAuthorizationGrantCode($transactionId);
14
+ public function getAuthorizationUrl();
15
+ public function getTokenUrl();
16
+ public function getCallbackUri();
17
+ }
18
+ }
Postman/Postman-Auth/PostmanAuthenticationManagerFactory.php CHANGED
@@ -1,58 +1,58 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
- if (! class_exists ( "PostmanAuthenticationManagerFactory" )) {
6
-
7
- require_once 'PostmanGoogleAuthenticationManager.php';
8
- require_once 'PostmanMicrosoftAuthenticationManager.php';
9
- require_once 'PostmanNonOAuthAuthenticationManager.php';
10
- require_once 'PostmanYahooAuthenticationManager.php';
11
-
12
- //
13
- class PostmanAuthenticationManagerFactory {
14
- private $logger;
15
-
16
- // singleton instance
17
- public static function getInstance() {
18
- static $inst = null;
19
- if ($inst === null) {
20
- $inst = new PostmanAuthenticationManagerFactory ();
21
- }
22
- return $inst;
23
- }
24
- private function __construct() {
25
- $this->logger = new PostmanLogger ( get_class ( $this ) );
26
- }
27
- public function createAuthenticationManager() {
28
- $transport = PostmanTransportRegistry::getInstance ()->getSelectedTransport ();
29
- return $this->createManager ( $transport );
30
- }
31
- private function createManager(PostmanZendModuleTransport $transport) {
32
- $options = PostmanOptions::getInstance ();
33
- $authorizationToken = PostmanOAuthToken::getInstance ();
34
- $authenticationType = $options->getAuthenticationType ();
35
- $hostname = $options->getHostname ();
36
- $clientId = $options->getClientId ();
37
- $clientSecret = $options->getClientSecret ();
38
- $senderEmail = $options->getMessageSenderEmail ();
39
- $scribe = $transport->getScribe ();
40
- $redirectUrl = $scribe->getCallbackUrl ();
41
- if ($transport->isOAuthUsed ( $options->getAuthenticationType () )) {
42
- if ($transport->isServiceProviderGoogle ( $hostname )) {
43
- $authenticationManager = new PostmanGoogleAuthenticationManager ( $clientId, $clientSecret, $authorizationToken, $redirectUrl, $senderEmail );
44
- } else if ($transport->isServiceProviderMicrosoft ( $hostname )) {
45
- $authenticationManager = new PostmanMicrosoftAuthenticationManager ( $clientId, $clientSecret, $authorizationToken, $redirectUrl );
46
- } else if ($transport->isServiceProviderYahoo ( $hostname )) {
47
- $authenticationManager = new PostmanYahooAuthenticationManager ( $clientId, $clientSecret, $authorizationToken, $redirectUrl );
48
- } else {
49
- assert ( false );
50
- }
51
- } else {
52
- $authenticationManager = new PostmanNonOAuthAuthenticationManager ();
53
- }
54
- $this->logger->debug ( 'Created ' . get_class ( $authenticationManager ) );
55
- return $authenticationManager;
56
- }
57
- }
58
  }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+ if (! class_exists ( "PostmanAuthenticationManagerFactory" )) {
6
+
7
+ require_once 'PostmanGoogleAuthenticationManager.php';
8
+ require_once 'PostmanMicrosoftAuthenticationManager.php';
9
+ require_once 'PostmanNonOAuthAuthenticationManager.php';
10
+ require_once 'PostmanYahooAuthenticationManager.php';
11
+
12
+ //
13
+ class PostmanAuthenticationManagerFactory {
14
+ private $logger;
15
+
16
+ // singleton instance
17
+ public static function getInstance() {
18
+ static $inst = null;
19
+ if ($inst === null) {
20
+ $inst = new PostmanAuthenticationManagerFactory ();
21
+ }
22
+ return $inst;
23
+ }
24
+ private function __construct() {
25
+ $this->logger = new PostmanLogger ( get_class ( $this ) );
26
+ }
27
+ public function createAuthenticationManager() {
28
+ $transport = PostmanTransportRegistry::getInstance ()->getSelectedTransport ();
29
+ return $this->createManager ( $transport );
30
+ }
31
+ private function createManager(PostmanZendModuleTransport $transport) {
32
+ $options = PostmanOptions::getInstance ();
33
+ $authorizationToken = PostmanOAuthToken::getInstance ();
34
+ $authenticationType = $options->getAuthenticationType ();
35
+ $hostname = $options->getHostname ();
36
+ $clientId = $options->getClientId ();
37
+ $clientSecret = $options->getClientSecret ();
38
+ $senderEmail = $options->getMessageSenderEmail ();
39
+ $scribe = $transport->getScribe ();
40
+ $redirectUrl = $scribe->getCallbackUrl ();
41
+ if ($transport->isOAuthUsed ( $options->getAuthenticationType () )) {
42
+ if ($transport->isServiceProviderGoogle ( $hostname )) {
43
+ $authenticationManager = new PostmanGoogleAuthenticationManager ( $clientId, $clientSecret, $authorizationToken, $redirectUrl, $senderEmail );
44
+ } else if ($transport->isServiceProviderMicrosoft ( $hostname )) {
45
+ $authenticationManager = new PostmanMicrosoftAuthenticationManager ( $clientId, $clientSecret, $authorizationToken, $redirectUrl );
46
+ } else if ($transport->isServiceProviderYahoo ( $hostname )) {
47
+ $authenticationManager = new PostmanYahooAuthenticationManager ( $clientId, $clientSecret, $authorizationToken, $redirectUrl );
48
+ } else {
49
+ assert ( false );
50
+ }
51
+ } else {
52
+ $authenticationManager = new PostmanNonOAuthAuthenticationManager ();
53
+ }
54
+ $this->logger->debug ( 'Created ' . get_class ( $authenticationManager ) );
55
+ return $authenticationManager;
56
+ }
57
+ }
58
  }
Postman/Postman-Auth/PostmanGoogleAuthenticationManager.php CHANGED
@@ -1,122 +1,122 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
- if (! class_exists ( "PostmanGoogleAuthenticationManager" )) {
6
-
7
- require_once 'PostmanAbstractAuthenticationManager.php';
8
- require_once 'PostmanStateIdMissingException.php';
9
-
10
- /**
11
- * https://developers.google.com/accounts/docs/OAuth2WebServer
12
- * https://developers.google.com/gmail/xoauth2_protocol
13
- * https://developers.google.com/gmail/api/auth/scopes
14
- */
15
- class PostmanGoogleAuthenticationManager extends PostmanAbstractAuthenticationManager implements PostmanAuthenticationManager {
16
-
17
- // This endpoint is the target of the initial request. It handles active session lookup, authenticating the user, and user consent.
18
- const GOOGLE_ENDPOINT = 'https://accounts.google.com/o/oauth2/auth';
19
- const GOOGLE_REFRESH = 'https://www.googleapis.com/oauth2/v3/token';
20
-
21
- // this scope doesn't work
22
- // Create, read, update, and delete drafts. Send messages and drafts.
23
- const SCOPE_COMPOSE = 'https://www.googleapis.com/auth/gmail.compose';
24
-
25
- // this scope doesn't work
26
- // All read/write operations except immediate, permanent deletion of threads and messages, bypassing Trash.
27
- const SCOPE_MODIFY = 'https://www.googleapis.com/auth/gmail.modify';
28
-
29
- // Full access to the account, including permanent deletion of threads and messages. This scope should only be requested if your application needs to immediately and permanently delete threads and messages, bypassing Trash; all other actions can be performed with less permissive scopes.
30
- const SCOPE_FULL_ACCESS = 'https://mail.google.com/';
31
- const AUTH_TEMP_ID = 'GOOGLE_OAUTH_TEMP_ID';
32
- const VENDOR_NAME = 'google';
33
- // the sender email address
34
- private $senderEmail;
35
-
36
- /**
37
- * Constructor
38
- *
39
- * Get a Client ID from https://account.live.com/developers/applications/index
40
- */
41
- public function __construct($clientId, $clientSecret, PostmanOAuthToken $authorizationToken, $callbackUri, $senderEmail) {
42
- assert ( ! empty ( $clientId ) );
43
- assert ( ! empty ( $clientSecret ) );
44
- assert ( ! empty ( $authorizationToken ) );
45
- assert ( ! empty ( $senderEmail ) );
46
- $logger = new PostmanLogger ( get_class ( $this ) );
47
- $this->senderEmail = $senderEmail;
48
- parent::__construct ( $logger, $clientId, $clientSecret, $authorizationToken, $callbackUri );
49
- }
50
-
51
- /**
52
- * The authorization sequence begins when your application redirects a browser to a Google URL;
53
- * the URL includes query parameters that indicate the type of access being requested.
54
- *
55
- * As in other scenarios, Google handles user authentication, session selection, and user consent.
56
- * The result is an authorization code, which Google returns to your application in a query string.
57
- *
58
- * (non-PHPdoc)
59
- *
60
- * @see PostmanAuthenticationManager::requestVerificationCode()
61
- */
62
- public function requestVerificationCode($transactionId) {
63
- $params = array (
64
- 'response_type' => 'code',
65
- 'redirect_uri' => urlencode ( $this->getCallbackUri () ),
66
- 'client_id' => $this->getClientId (),
67
- 'scope' => urlencode ( self::SCOPE_FULL_ACCESS ),
68
- 'access_type' => 'offline',
69
- 'approval_prompt' => 'force',
70
- 'state' => $transactionId,
71
- 'login_hint' => $this->senderEmail
72
- );
73
-
74
- $authUrl = $this->getAuthorizationUrl () . '?' . build_query ( $params );
75
-
76
- $this->getLogger ()->debug ( 'Requesting verification code from Google' );
77
- PostmanUtils::redirect ( $authUrl );
78
- }
79
-
80
- /**
81
- * After receiving the authorization code, your application can exchange the code
82
- * (along with a client ID and client secret) for an access token and, in some cases,
83
- * a refresh token.
84
- *
85
- * This code is identical for Google and Hotmail
86
- *
87
- * @see PostmanAuthenticationManager::processAuthorizationGrantCode()
88
- */
89
- public function processAuthorizationGrantCode($transactionId) {
90
- if (isset ( $_GET ['code'] )) {
91
- $this->getLogger ()->debug ( 'Found authorization code in request header' );
92
- $code = filter_input( INPUT_GET, 'code', FILTER_SANITIZE_STRING );
93
- if (isset ( $_GET ['state'] ) && $_GET ['state'] == $transactionId) {
94
- $this->getLogger ()->debug ( 'Found valid state in request header' );
95
- } else {
96
- $this->getLogger ()->error ( 'The grant code from Google had no accompanying state and may be a forgery' );
97
- throw new PostmanStateIdMissingException ();
98
- }
99
- $postvals = array (
100
- 'client_id' => $this->getClientId (),
101
- 'client_secret' => $this->getClientSecret (),
102
- 'grant_type' => 'authorization_code',
103
- 'redirect_uri' => $this->getCallbackUri (),
104
- 'code' => $code
105
- );
106
- $response = PostmanUtils::remotePostGetBodyOnly ( $this->getTokenUrl (), $postvals );
107
- $this->processResponse ( $response );
108
- $this->getAuthorizationToken ()->setVendorName ( self::VENDOR_NAME );
109
- return true;
110
- } else {
111
- $this->getLogger ()->debug ( 'Expected code in the request header but found none - user probably denied request' );
112
- return false;
113
- }
114
- }
115
- public function getAuthorizationUrl() {
116
- return self::GOOGLE_ENDPOINT;
117
- }
118
- public function getTokenUrl() {
119
- return self::GOOGLE_REFRESH;
120
- }
121
- }
122
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+ if (! class_exists ( "PostmanGoogleAuthenticationManager" )) {
6
+
7
+ require_once 'PostmanAbstractAuthenticationManager.php';
8
+ require_once 'PostmanStateIdMissingException.php';
9
+
10
+ /**
11
+ * https://developers.google.com/accounts/docs/OAuth2WebServer
12
+ * https://developers.google.com/gmail/xoauth2_protocol
13
+ * https://developers.google.com/gmail/api/auth/scopes
14
+ */
15
+ class PostmanGoogleAuthenticationManager extends PostmanAbstractAuthenticationManager implements PostmanAuthenticationManager {
16
+
17
+ // This endpoint is the target of the initial request. It handles active session lookup, authenticating the user, and user consent.
18
+ const GOOGLE_ENDPOINT = 'https://accounts.google.com/o/oauth2/auth';
19
+ const GOOGLE_REFRESH = 'https://www.googleapis.com/oauth2/v3/token';
20
+
21
+ // this scope doesn't work
22
+ // Create, read, update, and delete drafts. Send messages and drafts.
23
+ const SCOPE_COMPOSE = 'https://www.googleapis.com/auth/gmail.compose';
24
+
25
+ // this scope doesn't work
26
+ // All read/write operations except immediate, permanent deletion of threads and messages, bypassing Trash.
27
+ const SCOPE_MODIFY = 'https://www.googleapis.com/auth/gmail.modify';
28
+
29
+ // Full access to the account, including permanent deletion of threads and messages. This scope should only be requested if your application needs to immediately and permanently delete threads and messages, bypassing Trash; all other actions can be performed with less permissive scopes.
30
+ const SCOPE_FULL_ACCESS = 'https://mail.google.com/';
31
+ const AUTH_TEMP_ID = 'GOOGLE_OAUTH_TEMP_ID';
32
+ const VENDOR_NAME = 'google';
33
+ // the sender email address
34
+ private $senderEmail;
35
+
36
+ /**
37
+ * Constructor
38
+ *
39
+ * Get a Client ID from https://account.live.com/developers/applications/index
40
+ */
41
+ public function __construct($clientId, $clientSecret, PostmanOAuthToken $authorizationToken, $callbackUri, $senderEmail) {
42
+ assert ( ! empty ( $clientId ) );
43
+ assert ( ! empty ( $clientSecret ) );
44
+ assert ( ! empty ( $authorizationToken ) );
45
+ assert ( ! empty ( $senderEmail ) );
46
+ $logger = new PostmanLogger ( get_class ( $this ) );
47
+ $this->senderEmail = $senderEmail;
48
+ parent::__construct ( $logger, $clientId, $clientSecret, $authorizationToken, $callbackUri );
49
+ }
50
+
51
+ /**
52
+ * The authorization sequence begins when your application redirects a browser to a Google URL;
53
+ * the URL includes query parameters that indicate the type of access being requested.
54
+ *
55
+ * As in other scenarios, Google handles user authentication, session selection, and user consent.
56
+ * The result is an authorization code, which Google returns to your application in a query string.
57
+ *
58
+ * (non-PHPdoc)
59
+ *
60
+ * @see PostmanAuthenticationManager::requestVerificationCode()
61
+ */
62
+ public function requestVerificationCode($transactionId) {
63
+ $params = array (
64
+ 'response_type' => 'code',
65
+ 'redirect_uri' => urlencode ( $this->getCallbackUri () ),
66
+ 'client_id' => $this->getClientId (),
67
+ 'scope' => urlencode ( self::SCOPE_FULL_ACCESS ),
68
+ 'access_type' => 'offline',
69
+ 'approval_prompt' => 'force',
70
+ 'state' => $transactionId,
71
+ 'login_hint' => $this->senderEmail
72
+ );
73
+
74
+ $authUrl = $this->getAuthorizationUrl () . '?' . build_query ( $params );
75
+
76
+ $this->getLogger ()->debug ( 'Requesting verification code from Google' );
77
+ PostmanUtils::redirect ( $authUrl );
78
+ }
79
+
80
+ /**
81
+ * After receiving the authorization code, your application can exchange the code
82
+ * (along with a client ID and client secret) for an access token and, in some cases,
83
+ * a refresh token.
84
+ *
85
+ * This code is identical for Google and Hotmail
86
+ *
87
+ * @see PostmanAuthenticationManager::processAuthorizationGrantCode()
88
+ */
89
+ public function processAuthorizationGrantCode($transactionId) {
90
+ if (isset ( $_GET ['code'] )) {
91
+ $this->getLogger ()->debug ( 'Found authorization code in request header' );
92
+ $code = filter_input( INPUT_GET, 'code', FILTER_SANITIZE_STRING );
93
+ if (isset ( $_GET ['state'] ) && $_GET ['state'] == $transactionId) {
94
+ $this->getLogger ()->debug ( 'Found valid state in request header' );
95
+ } else {
96
+ $this->getLogger ()->error ( 'The grant code from Google had no accompanying state and may be a forgery' );
97
+ throw new PostmanStateIdMissingException ();
98
+ }
99
+ $postvals = array (
100
+ 'client_id' => $this->getClientId (),
101
+ 'client_secret' => $this->getClientSecret (),
102
+ 'grant_type' => 'authorization_code',
103
+ 'redirect_uri' => $this->getCallbackUri (),
104
+ 'code' => $code
105
+ );
106
+ $response = PostmanUtils::remotePostGetBodyOnly ( $this->getTokenUrl (), $postvals );
107
+ $this->processResponse ( $response );
108
+ $this->getAuthorizationToken ()->setVendorName ( self::VENDOR_NAME );
109
+ return true;
110
+ } else {
111
+ $this->getLogger ()->debug ( 'Expected code in the request header but found none - user probably denied request' );
112
+ return false;
113
+ }
114
+ }
115
+ public function getAuthorizationUrl() {
116
+ return self::GOOGLE_ENDPOINT;
117
+ }
118
+ public function getTokenUrl() {
119
+ return self::GOOGLE_REFRESH;
120
+ }
121
+ }
122
+ }
Postman/Postman-Auth/PostmanMicrosoftAuthenticationManager.php CHANGED
@@ -1,107 +1,107 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
- if (! class_exists ( "PostmanMicrosoftAuthenticationManager" )) {
6
-
7
- require_once 'PostmanAbstractAuthenticationManager.php';
8
-
9
- /**
10
- * https://msdn.microsoft.com/en-us/library/hh243647.aspx (Seems to be the most up-to-date doc on OAuth 2.0
11
- * https://msdn.microsoft.com/en-us/library/hh243649.aspx (Seems to be the most up-to-date examples on using the API)
12
- * https://msdn.microsoft.com/en-us/library/ff750690.aspx OAuth WRAP (Messenger Connect)
13
- * https://msdn.microsoft.com/en-us/library/ff749624.aspx Working with OAuth WRAP (Messenger Connect)
14
- * https://gist.github.com/kayalshri/5262641 Working example from Giriraj Namachivayam (kayalshri)
15
- */
16
- class PostmanMicrosoftAuthenticationManager extends PostmanAbstractAuthenticationManager implements PostmanAuthenticationManager {
17
-
18
- // constants
19
- const WINDOWS_LIVE_ENDPOINT = 'https://login.live.com/oauth20_authorize.srf';
20
- const WINDOWS_LIVE_REFRESH = 'https://login.live.com/oauth20_token.srf';
21
-
22
- // http://stackoverflow.com/questions/7163786/messenger-connect-oauth-wrap-api-to-get-user-emails
23
- // http://quabr.com/26329398/outlook-oauth-send-emails-with-wl-imap-scope-in-php
24
- const SCOPE = 'wl.imap,wl.offline_access';
25
- const VENDOR_NAME = 'microsoft';
26
-
27
- /**
28
- * Constructor
29
- *
30
- * Get a Client ID from https://account.live.com/developers/applications/index
31
- */
32
- public function __construct($clientId, $clientSecret, PostmanOAuthToken $authorizationToken, $callbackUri) {
33
- assert ( ! empty ( $clientId ) );
34
- assert ( ! empty ( $clientSecret ) );
35
- assert ( ! empty ( $authorizationToken ) );
36
- assert ( ! empty ( $callbackUri ) );
37
- $logger = new PostmanLogger ( get_class ( $this ) );
38
- parent::__construct ( $logger, $clientId, $clientSecret, $authorizationToken, $callbackUri );
39
- }
40
-
41
- /**
42
- * **********************************************
43
- * Request Verification Code
44
- * https://msdn.microsoft.com/en-us/library/ff749592.aspx
45
- *
46
- * The following example shows a URL that enables
47
- * a user to provide consent to an application by
48
- * using a Windows Live ID.
49
- *
50
- * When successful, this URL returns the user to
51
- * your application, along with a verification
52
- * code.
53
- * **********************************************
54
- */
55
- public function requestVerificationCode($transactionId) {
56
- $params = array (
57
- 'response_type' => 'code',
58
- 'redirect_uri' => urlencode ( $this->getCallbackUri () ),
59
- 'client_id' => $this->getClientId (),
60
- 'client_secret' => $this->getClientSecret (),
61
- 'scope' => urlencode ( self::SCOPE ),
62
- 'access_type' => 'offline',
63
- 'approval_prompt' => 'force'
64
- );
65
-
66
- $authUrl = $this->getAuthorizationUrl () . '?' . build_query ( $params );
67
-
68
- $this->getLogger ()->debug ( 'Requesting verification code from Microsoft' );
69
- PostmanUtils::redirect ( $authUrl );
70
- }
71
-
72
- /**
73
- * **********************************************
74
- * If we have a code back from the OAuth 2.0 flow,
75
- * we need to exchange that for an access token.
76
- * We store the resultant access token
77
- * bundle in the session, and redirect to ourself.
78
- * **********************************************
79
- */
80
- public function processAuthorizationGrantCode($transactionId) {
81
- if (isset ( $_GET ['code'] )) {
82
- $code = filter_input( INPUT_GET, 'code', FILTER_SANITIZE_STRING );
83
- $this->getLogger ()->debug ( 'Found authorization code in request header' );
84
- $postvals = array (
85
- 'client_id' => $this->getClientId (),
86
- 'client_secret' => $this->getClientSecret (),
87
- 'grant_type' => 'authorization_code',
88
- 'redirect_uri' => $this->getCallbackUri (),
89
- 'code' => $code
90
- );
91
- $response = PostmanUtils::remotePostGetBodyOnly ( $this->getTokenUrl (), $postvals );
92
- $this->processResponse ( $response );
93
- $this->getAuthorizationToken ()->setVendorName ( self::VENDOR_NAME );
94
- return true;
95
- } else {
96
- $this->getLogger ()->debug ( 'Expected code in the request header but found none - user probably denied request' );
97
- return false;
98
- }
99
- }
100
- public function getAuthorizationUrl() {
101
- return self::WINDOWS_LIVE_ENDPOINT;
102
- }
103
- public function getTokenUrl() {
104
- return self::WINDOWS_LIVE_REFRESH;
105
- }
106
- }
107
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+ if (! class_exists ( "PostmanMicrosoftAuthenticationManager" )) {
6
+
7
+ require_once 'PostmanAbstractAuthenticationManager.php';
8
+
9
+ /**
10
+ * https://msdn.microsoft.com/en-us/library/hh243647.aspx (Seems to be the most up-to-date doc on OAuth 2.0
11
+ * https://msdn.microsoft.com/en-us/library/hh243649.aspx (Seems to be the most up-to-date examples on using the API)
12
+ * https://msdn.microsoft.com/en-us/library/ff750690.aspx OAuth WRAP (Messenger Connect)
13
+ * https://msdn.microsoft.com/en-us/library/ff749624.aspx Working with OAuth WRAP (Messenger Connect)
14
+ * https://gist.github.com/kayalshri/5262641 Working example from Giriraj Namachivayam (kayalshri)
15
+ */
16
+ class PostmanMicrosoftAuthenticationManager extends PostmanAbstractAuthenticationManager implements PostmanAuthenticationManager {
17
+
18
+ // constants
19
+ const WINDOWS_LIVE_ENDPOINT = 'https://login.live.com/oauth20_authorize.srf';
20
+ const WINDOWS_LIVE_REFRESH = 'https://login.live.com/oauth20_token.srf';
21
+
22
+ // http://stackoverflow.com/questions/7163786/messenger-connect-oauth-wrap-api-to-get-user-emails
23
+ // http://quabr.com/26329398/outlook-oauth-send-emails-with-wl-imap-scope-in-php
24
+ const SCOPE = 'wl.imap,wl.offline_access';
25
+ const VENDOR_NAME = 'microsoft';
26
+
27
+ /**
28
+ * Constructor
29
+ *
30
+ * Get a Client ID from https://account.live.com/developers/applications/index
31
+ */
32
+ public function __construct($clientId, $clientSecret, PostmanOAuthToken $authorizationToken, $callbackUri) {
33
+ assert ( ! empty ( $clientId ) );
34
+ assert ( ! empty ( $clientSecret ) );
35
+ assert ( ! empty ( $authorizationToken ) );
36
+ assert ( ! empty ( $callbackUri ) );
37
+ $logger = new PostmanLogger ( get_class ( $this ) );
38
+ parent::__construct ( $logger, $clientId, $clientSecret, $authorizationToken, $callbackUri );
39
+ }
40
+
41
+ /**
42
+ * **********************************************
43
+ * Request Verification Code
44
+ * https://msdn.microsoft.com/en-us/library/ff749592.aspx
45
+ *
46
+ * The following example shows a URL that enables
47
+ * a user to provide consent to an application by
48
+ * using a Windows Live ID.
49
+ *
50
+ * When successful, this URL returns the user to
51
+ * your application, along with a verification
52
+ * code.
53
+ * **********************************************
54
+ */
55
+ public function requestVerificationCode($transactionId) {
56
+ $params = array (
57
+ 'response_type' => 'code',
58
+ 'redirect_uri' => urlencode ( $this->getCallbackUri () ),
59
+ 'client_id' => $this->getClientId (),
60
+ 'client_secret' => $this->getClientSecret (),
61
+ 'scope' => urlencode ( self::SCOPE ),
62
+ 'access_type' => 'offline',
63
+ 'approval_prompt' => 'force'
64
+ );
65
+
66
+ $authUrl = $this->getAuthorizationUrl () . '?' . build_query ( $params );
67
+
68
+ $this->getLogger ()->debug ( 'Requesting verification code from Microsoft' );
69
+ PostmanUtils::redirect ( $authUrl );
70
+ }
71
+
72
+ /**
73
+ * **********************************************
74
+ * If we have a code back from the OAuth 2.0 flow,
75
+ * we need to exchange that for an access token.
76
+ * We store the resultant access token
77
+ * bundle in the session, and redirect to ourself.
78
+ * **********************************************
79
+ */
80
+ public function processAuthorizationGrantCode($transactionId) {
81
+ if (isset ( $_GET ['code'] )) {
82
+ $code = filter_input( INPUT_GET, 'code', FILTER_SANITIZE_STRING );
83
+ $this->getLogger ()->debug ( 'Found authorization code in request header' );
84
+ $postvals = array (
85
+ 'client_id' => $this->getClientId (),
86
+ 'client_secret' => $this->getClientSecret (),
87
+ 'grant_type' => 'authorization_code',
88
+ 'redirect_uri' => $this->getCallbackUri (),
89
+ 'code' => $code
90
+ );
91
+ $response = PostmanUtils::remotePostGetBodyOnly ( $this->getTokenUrl (), $postvals );
92
+ $this->processResponse ( $response );
93
+ $this->getAuthorizationToken ()->setVendorName ( self::VENDOR_NAME );
94
+ return true;
95
+ } else {
96
+ $this->getLogger ()->debug ( 'Expected code in the request header but found none - user probably denied request' );
97
+ return false;
98
+ }
99
+ }
100
+ public function getAuthorizationUrl() {
101
+ return self::WINDOWS_LIVE_ENDPOINT;
102
+ }
103
+ public function getTokenUrl() {
104
+ return self::WINDOWS_LIVE_REFRESH;
105
+ }
106
+ }
107
+ }
Postman/Postman-Auth/PostmanNonOAuthAuthenticationManager.php CHANGED
@@ -1,46 +1,46 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
- if (! class_exists ( "PostmanNonOAuthAuthenticationManager" )) {
6
-
7
- require_once 'PostmanAuthenticationManager.php';
8
- class PostmanNonOAuthAuthenticationManager implements PostmanAuthenticationManager {
9
-
10
- /**
11
- */
12
- public function isAccessTokenExpired() {
13
- return false;
14
- }
15
-
16
- /**
17
- * (non-PHPdoc)
18
- *
19
- * @see PostmanAuthenticationManager::requestVerificationCode()
20
- */
21
- public function requestVerificationCode($transactionId) {
22
- // otherwise known as IllegaStateException
23
- assert ( false );
24
- }
25
- public function processAuthorizationGrantCode($transactionId) {
26
- // otherwise known as IllegaStateException
27
- assert ( false );
28
- }
29
- public function refreshToken() {
30
- // no-op
31
- }
32
- public function getAuthorizationUrl() {
33
- return null;
34
- }
35
- public function getTokenUrl() {
36
- return null;
37
- }
38
- public function getCallbackUri() {
39
- return null;
40
- }
41
- public function generateRequestTransactionId() {
42
- // otherwise known as IllegaStateException
43
- assert ( false );
44
- }
45
- }
46
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+ if (! class_exists ( "PostmanNonOAuthAuthenticationManager" )) {
6
+
7
+ require_once 'PostmanAuthenticationManager.php';
8
+ class PostmanNonOAuthAuthenticationManager implements PostmanAuthenticationManager {
9
+
10
+ /**
11
+ */
12
+ public function isAccessTokenExpired() {
13
+ return false;
14
+ }
15
+
16
+ /**
17
+ * (non-PHPdoc)
18
+ *
19
+ * @see PostmanAuthenticationManager::requestVerificationCode()
20
+ */
21
+ public function requestVerificationCode($transactionId) {
22
+ // otherwise known as IllegaStateException
23
+ assert ( false );
24
+ }
25
+ public function processAuthorizationGrantCode($transactionId) {
26
+ // otherwise known as IllegaStateException
27
+ assert ( false );
28
+ }
29
+ public function refreshToken() {
30
+ // no-op
31
+ }
32
+ public function getAuthorizationUrl() {
33
+ return null;
34
+ }
35
+ public function getTokenUrl() {
36
+ return null;
37
+ }
38
+ public function getCallbackUri() {
39
+ return null;
40
+ }
41
+ public function generateRequestTransactionId() {
42
+ // otherwise known as IllegaStateException
43
+ assert ( false );
44
+ }
45
+ }
46
+ }
Postman/Postman-Auth/PostmanStateIdMissingException.php CHANGED
@@ -1,8 +1,8 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
- if (! class_exists ( 'PostmanStateIdMissingException' )) {
6
- class PostmanStateIdMissingException extends Exception {
7
- }
8
  }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+ if (! class_exists ( 'PostmanStateIdMissingException' )) {
6
+ class PostmanStateIdMissingException extends Exception {
7
+ }
8
  }
Postman/Postman-Auth/PostmanYahooAuthenticationManager.php CHANGED
@@ -1,136 +1,136 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
- if (! class_exists ( "PostmanYahooAuthenticationManager" )) {
6
-
7
- require_once 'PostmanAbstractAuthenticationManager.php';
8
- require_once 'PostmanStateIdMissingException.php';
9
-
10
- /**
11
- * Super-simple.
12
- * I should have started with Yahoo.
13
- *
14
- * https://developer.yahoo.com/oauth2/guide/
15
- * Get a Client ID at https://developer.apps.yahoo.com/projects
16
- *
17
- * @author jasonhendriks
18
- */
19
- class PostmanYahooAuthenticationManager extends PostmanAbstractAuthenticationManager implements PostmanAuthenticationManager {
20
-
21
- // This endpoint is the target of the initial request. It handles active session lookup, authenticating the user, and user consent.
22
- const AUTHORIZATION_URL = 'https://api.login.yahoo.com/oauth2/request_auth';
23
- const GET_TOKEN_URL = 'https://api.login.yahoo.com/oauth2/get_token';
24
-
25
- // The SESSION key for the OAuth Transaction Id
26
- const AUTH_TEMP_ID = 'OAUTH_TEMP_ID';
27
- const VENDOR_NAME = 'yahoo';
28
-
29
- /**
30
- * Constructor
31
- *
32
- * Get a Client ID from https://account.live.com/developers/applications/index
33
- */
34
- public function __construct($clientId, $clientSecret, PostmanOAuthToken $authorizationToken, $callbackUri) {
35
- assert ( ! empty ( $clientId ) );
36
- assert ( ! empty ( $clientSecret ) );
37
- assert ( ! empty ( $authorizationToken ) );
38
- assert ( ! empty ( $callbackUri ) );
39
- $logger = new PostmanLogger ( get_class ( $this ) );
40
- parent::__construct ( $logger, $clientId, $clientSecret, $authorizationToken, $callbackUri );
41
- }
42
-
43
- /**
44
- * The authorization sequence begins when your application redirects a browser to a Google URL;
45
- * the URL includes query parameters that indicate the type of access being requested.
46
- *
47
- * As in other scenarios, Google handles user authentication, session selection, and user consent.
48
- * The result is an authorization code, which Google returns to your application in a query string.
49
- *
50
- * (non-PHPdoc)
51
- *
52
- * @see PostmanAuthenticationManager::requestVerificationCode()
53
- */
54
- public function requestVerificationCode($transactionId) {
55
- $params = array (
56
- 'response_type' => 'code',
57
- 'redirect_uri' => urlencode ( $this->getCallbackUri () ),
58
- 'client_id' => $this->getClientId (),
59
- 'state' => $transactionId,
60
- 'language' => get_locale ()
61
- );
62
-
63
- $authUrl = $this->getAuthorizationUrl () . '?' . build_query ( $params );
64
-
65
- $this->getLogger ()->debug ( 'Requesting verification code from Yahoo' );
66
- PostmanUtils::redirect ( $authUrl );
67
- }
68
-
69
- /**
70
- * After receiving the authorization code, your application can exchange the code
71
- * (along with a client ID and client secret) for an access token and, in some cases,
72
- * a refresh token.
73
- *
74
- * (non-PHPdoc)
75
- *
76
- * @see PostmanAuthenticationManager::processAuthorizationGrantCode()
77
- */
78
- public function processAuthorizationGrantCode($transactionId) {
79
- if (isset ( $_GET ['code'] )) {
80
- $code = filter_input( INPUT_GET, 'code', FILTER_SANITIZE_STRING );
81
- $this->getLogger ()->debug ( sprintf ( 'Found authorization code %s in request header', $code ) );
82
- if (isset ( $_GET ['state'] ) && $_GET ['state'] == $transactionId) {
83
- $this->getLogger ()->debug ( 'Found valid state in request header' );
84
- } else {
85
- $this->getLogger ()->error ( 'The grant code from Yahoo had no accompanying state and may be a forgery' );
86
- throw new PostmanStateIdMissingException ();
87
- }
88
- // Note: The Authorization: Basic authorization header is generated through a Base64 encoding of client_id:client_secret per RFC 2617.
89
- // header("Authorization: Basic " . base64_encode($username . ":" . $password);
90
- $headers = array (
91
- 'Authorization' => sprintf ( "Basic %s", base64_encode ( $this->getClientId () . ':' . $this->getClientSecret () ) )
92
- );
93
- $postvals = array (
94
- 'code' => $code,
95
- 'grant_type' => 'authorization_code',
96
- 'redirect_uri' => $this->getCallbackUri ()
97
- );
98
- $response = PostmanUtils::remotePostGetBodyOnly ( $this->getTokenUrl (), $postvals, $headers );
99
- $this->processResponse ( $response );
100
- $this->getAuthorizationToken ()->setVendorName ( self::VENDOR_NAME );
101
- return true;
102
- } else {
103
- $this->getLogger ()->debug ( 'Expected code in the request header but found none - user probably denied request' );
104
- return false;
105
- }
106
- }
107
-
108
- /**
109
- * Step 5: Exchange refresh token for new access token
110
- * After the access token expires, you can use the refresh token, which has a long lifetime, to get a new access token.
111
- */
112
- public function refreshToken() {
113
- $this->getLogger ()->debug ( 'Refreshing Token' );
114
- $refreshUrl = $this->getTokenUrl ();
115
- $callbackUrl = $this->getCallbackUri ();
116
- assert ( ! empty ( $refreshUrl ) );
117
- assert ( ! empty ( $callbackUrl ) );
118
- $headers = array (
119
- 'Authorization' => sprintf ( "Basic %s", base64_encode ( $this->getClientId () . ':' . $this->getClientSecret () ) )
120
- );
121
- $postvals = array (
122
- 'redirect_uri' => $callbackUrl,
123
- 'grant_type' => 'refresh_token',
124
- 'refresh_token' => $this->getAuthorizationToken ()->getRefreshToken ()
125
- );
126
- $response = PostmanUtils::remotePostGetBodyOnly ( $this->getTokenUrl (), $postvals, $headers );
127
- $this->processResponse ( $response );
128
- }
129
- public function getAuthorizationUrl() {
130
- return self::AUTHORIZATION_URL;
131
- }
132
- public function getTokenUrl() {
133
- return self::GET_TOKEN_URL;
134
- }
135
- }
136
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+ if (! class_exists ( "PostmanYahooAuthenticationManager" )) {
6
+
7
+ require_once 'PostmanAbstractAuthenticationManager.php';
8
+ require_once 'PostmanStateIdMissingException.php';
9
+
10
+ /**
11
+ * Super-simple.
12
+ * I should have started with Yahoo.
13
+ *
14
+ * https://developer.yahoo.com/oauth2/guide/
15
+ * Get a Client ID at https://developer.apps.yahoo.com/projects
16
+ *
17
+ * @author jasonhendriks
18
+ */
19
+ class PostmanYahooAuthenticationManager extends PostmanAbstractAuthenticationManager implements PostmanAuthenticationManager {
20
+
21
+ // This endpoint is the target of the initial request. It handles active session lookup, authenticating the user, and user consent.
22
+ const AUTHORIZATION_URL = 'https://api.login.yahoo.com/oauth2/request_auth';
23
+ const GET_TOKEN_URL = 'https://api.login.yahoo.com/oauth2/get_token';
24
+
25
+ // The SESSION key for the OAuth Transaction Id
26
+ const AUTH_TEMP_ID = 'OAUTH_TEMP_ID';
27
+ const VENDOR_NAME = 'yahoo';
28
+
29
+ /**
30
+ * Constructor
31
+ *
32
+ * Get a Client ID from https://account.live.com/developers/applications/index
33
+ */
34
+ public function __construct($clientId, $clientSecret, PostmanOAuthToken $authorizationToken, $callbackUri) {
35
+ assert ( ! empty ( $clientId ) );
36
+ assert ( ! empty ( $clientSecret ) );
37
+ assert ( ! empty ( $authorizationToken ) );
38
+ assert ( ! empty ( $callbackUri ) );
39
+ $logger = new PostmanLogger ( get_class ( $this ) );
40
+ parent::__construct ( $logger, $clientId, $clientSecret, $authorizationToken, $callbackUri );
41
+ }
42
+
43
+ /**
44
+ * The authorization sequence begins when your application redirects a browser to a Google URL;
45
+ * the URL includes query parameters that indicate the type of access being requested.
46
+ *
47
+ * As in other scenarios, Google handles user authentication, session selection, and user consent.
48
+ * The result is an authorization code, which Google returns to your application in a query string.
49
+ *
50
+ * (non-PHPdoc)
51
+ *
52
+ * @see PostmanAuthenticationManager::requestVerificationCode()
53
+ */
54
+ public function requestVerificationCode($transactionId) {
55
+ $params = array (
56
+ 'response_type' => 'code',
57
+ 'redirect_uri' => urlencode ( $this->getCallbackUri () ),
58
+ 'client_id' => $this->getClientId (),
59
+ 'state' => $transactionId,
60
+ 'language' => get_locale ()
61
+ );
62
+
63
+ $authUrl = $this->getAuthorizationUrl () . '?' . build_query ( $params );
64
+
65
+ $this->getLogger ()->debug ( 'Requesting verification code from Yahoo' );
66
+ PostmanUtils::redirect ( $authUrl );
67
+ }
68
+
69
+ /**
70
+ * After receiving the authorization code, your application can exchange the code
71
+ * (along with a client ID and client secret) for an access token and, in some cases,
72
+ * a refresh token.
73
+ *
74
+ * (non-PHPdoc)
75
+ *
76
+ * @see PostmanAuthenticationManager::processAuthorizationGrantCode()
77
+ */
78
+ public function processAuthorizationGrantCode($transactionId) {
79
+ if (isset ( $_GET ['code'] )) {
80
+ $code = filter_input( INPUT_GET, 'code', FILTER_SANITIZE_STRING );
81
+ $this->getLogger ()->debug ( sprintf ( 'Found authorization code %s in request header', $code ) );
82
+ if (isset ( $_GET ['state'] ) && $_GET ['state'] == $transactionId) {
83
+ $this->getLogger ()->debug ( 'Found valid state in request header' );
84
+ } else {
85
+ $this->getLogger ()->error ( 'The grant code from Yahoo had no accompanying state and may be a forgery' );
86
+ throw new PostmanStateIdMissingException ();
87
+ }
88
+ // Note: The Authorization: Basic authorization header is generated through a Base64 encoding of client_id:client_secret per RFC 2617.
89
+ // header("Authorization: Basic " . base64_encode($username . ":" . $password);
90
+ $headers = array (
91
+ 'Authorization' => sprintf ( "Basic %s", base64_encode ( $this->getClientId () . ':' . $this->getClientSecret () ) )
92
+ );
93
+ $postvals = array (
94
+ 'code' => $code,
95
+ 'grant_type' => 'authorization_code',
96
+ 'redirect_uri' => $this->getCallbackUri ()
97
+ );
98
+ $response = PostmanUtils::remotePostGetBodyOnly ( $this->getTokenUrl (), $postvals, $headers );
99
+ $this->processResponse ( $response );
100
+ $this->getAuthorizationToken ()->setVendorName ( self::VENDOR_NAME );
101
+ return true;
102
+ } else {
103
+ $this->getLogger ()->debug ( 'Expected code in the request header but found none - user probably denied request' );
104
+ return false;
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Step 5: Exchange refresh token for new access token
110
+ * After the access token expires, you can use the refresh token, which has a long lifetime, to get a new access token.
111
+ */
112
+ public function refreshToken() {
113
+ $this->getLogger ()->debug ( 'Refreshing Token' );
114
+ $refreshUrl = $this->getTokenUrl ();
115
+ $callbackUrl = $this->getCallbackUri ();
116
+ assert ( ! empty ( $refreshUrl ) );
117
+ assert ( ! empty ( $callbackUrl ) );
118
+ $headers = array (
119
+ 'Authorization' => sprintf ( "Basic %s", base64_encode ( $this->getClientId () . ':' . $this->getClientSecret () ) )
120
+ );
121
+ $postvals = array (
122
+ 'redirect_uri' => $callbackUrl,
123
+ 'grant_type' => 'refresh_token',
124
+ 'refresh_token' => $this->getAuthorizationToken ()->getRefreshToken ()
125
+ );
126
+ $response = PostmanUtils::remotePostGetBodyOnly ( $this->getTokenUrl (), $postvals, $headers );
127
+ $this->processResponse ( $response );
128
+ }
129
+ public function getAuthorizationUrl() {
130
+ return self::AUTHORIZATION_URL;
131
+ }
132
+ public function getTokenUrl() {
133
+ return self::GET_TOKEN_URL;
134
+ }
135
+ }
136
+ }
Postman/Postman-Configuration/PostmanConfigurationController.php CHANGED
@@ -1,1099 +1,1099 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- require_once( 'PostmanRegisterConfigurationSettings.php' );
7
- class PostmanConfigurationController {
8
- const CONFIGURATION_SLUG = 'postman/configuration';
9
- const CONFIGURATION_WIZARD_SLUG = 'postman/configuration_wizard';
10
-
11
- // logging
12
- private $logger;
13
- private $options;
14
- private $settingsRegistry;
15
-
16
- // Holds the values to be used in the fields callbacks
17
- private $rootPluginFilenameAndPath;
18
-
19
- private $importableConfiguration;
20
-
21
- /**
22
- * Constructor
23
- *
24
- * @param mixed $rootPluginFilenameAndPath
25
- */
26
- public function __construct( $rootPluginFilenameAndPath ) {
27
-
28
- assert( ! empty( $rootPluginFilenameAndPath ) );
29
- assert( PostmanUtils::isAdmin() );
30
- assert( is_admin() );
31
-
32
- $this->logger = new PostmanLogger( get_class( $this ) );
33
- $this->rootPluginFilenameAndPath = $rootPluginFilenameAndPath;
34
- $this->options = PostmanOptions::getInstance();
35
- $this->settingsRegistry = new PostmanSettingsRegistry();
36
-
37
- PostmanUtils::registerAdminMenu( $this, 'addSetupWizardSubmenu' );
38
-
39
- // hook on the init event
40
- add_action( 'init', array(
41
- $this,
42
- 'on_init',
43
- ) );
44
-
45
- // initialize the scripts, stylesheets and form fields
46
- add_action( 'admin_init', array(
47
- $this,
48
- 'on_admin_init',
49
- ) );
50
-
51
- add_action( 'admin_menu', array( $this, 'add_submenu_page' ), 21 );
52
-
53
- }
54
-
55
- /**
56
- * Functions to execute on the init event
57
- *
58
- * "Typically used by plugins to initialize. The current user is already authenticated by this time."
59
- * ref: http://codex.wordpress.org/Plugin_API/Action_Reference#Actions_Run_During_a_Typical_Request
60
- */
61
- public function on_init() {
62
- // register Ajax handlers
63
- new PostmanGetHostnameByEmailAjaxController();
64
- new PostmanManageConfigurationAjaxHandler();
65
- new PostmanImportConfigurationAjaxController( $this->options );
66
- }
67
-
68
- /**
69
- * Fires on the admin_init method
70
- */
71
- public function on_admin_init() {
72
- $this->registerStylesAndScripts();
73
- $this->settingsRegistry->on_admin_init();
74
- }
75
-
76
- /**
77
- * Register and add settings
78
- */
79
- private function registerStylesAndScripts() {
80
- if ( $this->logger->isTrace() ) {
81
- $this->logger->trace( 'registerStylesAndScripts()' );
82
- }
83
- // register the stylesheet and javascript external resources
84
- $pluginData = apply_filters( 'postman_get_plugin_metadata', null );
85
-
86
- wp_register_script( 'postman_manual_config_script', plugins_url( 'Postman/Postman-Configuration/postman_manual_config.js', $this->rootPluginFilenameAndPath ), array(
87
- PostmanViewController::JQUERY_SCRIPT,
88
- 'jquery-ui-core',
89
- 'jquery-ui-tabs',
90
- 'jquery_validation',
91
- PostmanViewController::POSTMAN_SCRIPT,
92
- ), $pluginData ['version'] );
93
-
94
- wp_register_script( 'postman_wizard_script', plugins_url( 'Postman/Postman-Configuration/postman_wizard.js', $this->rootPluginFilenameAndPath ), array(
95
- PostmanViewController::JQUERY_SCRIPT,
96
- 'jquery_validation',
97
- 'jquery_steps_script',
98
- PostmanViewController::POSTMAN_SCRIPT,
99
- 'sprintf',
100
- ), $pluginData ['version'] );
101
- }
102
-
103
- /**
104
- */
105
- private function addLocalizeScriptsToPage() {
106
-
107
- // the transport modules scripts
108
- foreach ( PostmanTransportRegistry::getInstance()->getTransports() as $transport ) {
109
- $transport->enqueueScript();
110
- }
111
-
112
- // we need data from port test
113
- PostmanConnectivityTestController::addLocalizeScriptForPortTest();
114
-
115
- }
116
-
117
- /**
118
- * Adds sub menu page `Settings`
119
- *
120
- * @since 2.1
121
- * @version 1.0
122
- */
123
- public function add_submenu_page() {
124
-
125
- // only do this for administrators
126
- if ( PostmanUtils::isAdmin() ) {
127
-
128
- $this->logger->trace( 'created PostmanSettings admin menu item' );
129
-
130
- $page = add_submenu_page(
131
- PostmanViewController::POSTMAN_MENU_SLUG,
132
- sprintf( __( '%s Setup', 'post-smtp' ), __( 'Postman SMTP', 'post-smtp' ) ),
133
- __( 'Settings', 'post-smtp' ),
134
- Postman::MANAGE_POSTMAN_CAPABILITY_NAME,
135
- PostmanConfigurationController::CONFIGURATION_SLUG,
136
- array(
137
- $this,
138
- 'outputManualConfigurationContent',
139
- ) );
140
-
141
- // When the plugin options page is loaded, also load the stylesheet
142
- add_action( 'admin_print_styles-' . $page, array( $this, 'enqueueConfigurationResources' ) );
143
-
144
- }
145
-
146
- }
147
-
148
- /**
149
- */
150
- function enqueueConfigurationResources() {
151
- $this->addLocalizeScriptsToPage();
152
- wp_enqueue_style( 'jquery_ui_style' );
153
- wp_enqueue_style( PostmanViewController::POSTMAN_STYLE );
154
- wp_enqueue_script( 'postman_manual_config_script' );
155
- }
156
-
157
- /**
158
- * Register the Setup Wizard screen
159
- */
160
- public function addSetupWizardSubmenu() {
161
- $page = add_submenu_page( null, sprintf( __( '%s Setup', 'post-smtp' ), __( 'Postman SMTP', 'post-smtp' ) ), __( 'Postman SMTP', 'post-smtp' ), Postman::MANAGE_POSTMAN_CAPABILITY_NAME, PostmanConfigurationController::CONFIGURATION_WIZARD_SLUG, array(
162
- $this,
163
- 'outputWizardContent',
164
- ) );
165
- // When the plugin options page is loaded, also load the stylesheet
166
- add_action( 'admin_print_styles-' . $page, array(
167
- $this,
168
- 'enqueueWizardResources',
169
- ) );
170
- }
171
-
172
- /**
173
- */
174
- function enqueueWizardResources() {
175
- $this->addLocalizeScriptsToPage();
176
- $this->importableConfiguration = new PostmanImportableConfiguration();
177
- $startPage = 1;
178
- if ( $this->importableConfiguration->isImportAvailable() ) {
179
- $startPage = 0;
180
- }
181
- wp_localize_script( PostmanViewController::POSTMAN_SCRIPT, 'postman_setup_wizard', array(
182
- 'start_page' => $startPage,
183
- ) );
184
- wp_enqueue_style( 'jquery_steps_style' );
185
- wp_enqueue_style( PostmanViewController::POSTMAN_STYLE );
186
- wp_enqueue_script( 'postman_wizard_script' );
187
-
188
- wp_localize_script( 'postman_wizard_script', 'postman',
189
- array(
190
- 'assets' => POST_SMTP_ASSETS
191
- )
192
- );
193
-
194
- //wp_localize_script( PostmanViewController::POSTMAN_SCRIPT, '$jq', 'jQuery.noConflict(true)' );
195
- $shortLocale = substr( get_locale(), 0, 2 );
196
- if ( $shortLocale != 'en' ) {
197
- $url = plugins_url( sprintf( 'script/jquery-validate/localization/messages_%s.js', $shortLocale ), $this->rootPluginFilenameAndPath );
198
- wp_enqueue_script( sprintf( 'jquery-validation-locale-%s', $shortLocale ), $url, array(), POST_SMTP_VER );
199
- }
200
- }
201
-
202
- /**
203
- */
204
- public function outputManualConfigurationContent() {
205
- print '<div class="wrap">';
206
-
207
- PostmanViewController::outputChildPageHeader( __( 'Settings', 'post-smtp' ), 'advanced_config' );
208
-
209
- $config_tabs = apply_filters( 'post_smtp_admin_tabs', array(
210
- 'account_config' => __( 'Account', 'post-smtp' ),
211
- 'fallback' => __( 'Fallback', 'post-smtp' ),
212
- 'message_config' => __( 'Message', 'post-smtp' ),
213
- 'logging_config' => __( 'Logging', 'post-smtp' ),
214
- 'advanced_options_config' => __( 'Advanced', 'post-smtp' ),
215
- ) );
216
-
217
- print '<div id="config_tabs"><ul>';
218
-
219
- foreach ( $config_tabs as $slug => $tab ) :
220
- printf( '<li><a href="#%s">%s</a></li>', esc_attr( $slug ), esc_html( $tab ) );
221
- endforeach;
222
-
223
- print '</ul>';
224
-
225
- print '<form method="post" action="options.php">';
226
-
227
- wp_nonce_field('post-smtp', 'security');
228
-
229
- // This prints out all hidden setting fields
230
- settings_fields( PostmanAdminController::SETTINGS_GROUP_NAME );
231
-
232
- // account_config
233
- print '<section id="account_config">';
234
- if ( sizeof( PostmanTransportRegistry::getInstance()->getTransports() ) > 1 ) {
235
- do_settings_sections( 'transport_options' );
236
- }
237
- else {
238
- printf(
239
- '<input id="input_%2$s" type="hidden" name="%1$s[%2$s]" value="%3$s"/>',
240
- esc_attr( PostmanOptions::POSTMAN_OPTIONS ),
241
- esc_attr( PostmanOptions::TRANSPORT_TYPE ),
242
- esc_attr( PostmanSmtpModuleTransport::SLUG )
243
- );
244
- }
245
- print '<div id="smtp_config" class="transport_setting">';
246
- do_settings_sections( PostmanAdminController::SMTP_OPTIONS );
247
- print '</div>';
248
- print '<div id="password_settings" class="authentication_setting non-oauth2">';
249
- do_settings_sections( PostmanAdminController::BASIC_AUTH_OPTIONS );
250
- print '</div>';
251
- print '<div id="oauth_settings" class="authentication_setting non-basic">';
252
- do_settings_sections( PostmanAdminController::OAUTH_AUTH_OPTIONS );
253
- print '</div>';
254
- print '<div id="mandrill_settings" class="authentication_setting non-basic non-oauth2">';
255
- do_settings_sections( PostmanMandrillTransport::MANDRILL_AUTH_OPTIONS );
256
- print '</div>';
257
- print '<div id="sendgrid_settings" class="authentication_setting non-basic non-oauth2">';
258
- do_settings_sections( PostmanSendGridTransport::SENDGRID_AUTH_OPTIONS );
259
- print '</div>';
260
- print '<div id="mailgun_settings" class="authentication_setting non-basic non-oauth2">';
261
- do_settings_sections( PostmanMailgunTransport::MAILGUN_AUTH_OPTIONS );
262
- print '</div>';
263
- print '<div id="sendinblue_settings" class="authentication_setting non-basic non-oauth2">';
264
- do_settings_sections( PostmanSendinblueTransport::SENDINBLUE_AUTH_OPTIONS );
265
- print '</div>';
266
- print '<div id="postmark_settings" class="authentication_setting non-basic non-oauth2">';
267
- do_settings_sections( PostmanPostmarkTransport::POSTMARK_AUTH_OPTIONS );
268
- print '</div>';
269
- print '<div id="sparkpost_settings" class="authentication_setting non-basic non-oauth2">';
270
- do_settings_sections( PostmanSparkPostTransport::SPARKPOST_AUTH_OPTIONS );
271
- print '</div>';
272
-
273
- do_action( 'post_smtp_settings_sections' );
274
-
275
- print '</section>';
276
- // end account config
277
- ?>
278
-
279
- <!-- Fallback Start -->
280
- <section id="fallback">
281
- <h2><?php esc_html_e( 'Failed emails fallback', 'post-smtp' ); ?></h2>
282
- <p><?php esc_html_e( 'By enable this option, if your email is fail to send Post SMTP will try to use the SMTP service you define here.', 'post-smtp' ); ?></p>
283
- <table class="form-table">
284
- <tr valign="">
285
- <th scope="row"><?php esc_html_e( 'Use Fallback?', 'post-smtp' ); ?></th>
286
- <td>
287
- <label>
288
- <input name="postman_options[<?php esc_attr_e( PostmanOptions::FALLBACK_SMTP_ENABLED ); ?>]" type="radio"
289
- value="no"<?php echo checked( $this->options->getFallbackIsEnabled(), 'no' ); ?>>
290
- <?php esc_html_e( 'No', 'post-smtp' ); ?>
291
- </label>
292
- &nbsp;
293
- <label>
294
- <?php $checked = checked( $this->options->getFallbackIsEnabled(), 'yes', false ); ?>
295
- <input name="postman_options[<?php esc_attr_e( PostmanOptions::FALLBACK_SMTP_ENABLED ); ?>]" type="radio"
296
- value="yes"<?php echo checked( $this->options->getFallbackIsEnabled(), 'yes' ); ?>>
297
- <?php esc_html_e( 'Yes', 'post-smtp' ); ?>
298
- </label>
299
- </td>
300
- </tr>
301
-
302
- <tr>
303
- <th scope="row"><?php esc_html_e('Outgoing Mail Server', 'post-smtp' ); ?></th>
304
- <?php $host = $this->options->getFallbackHostname(); ?>
305
- <td>
306
- <input type="text" id="fallback-smtp-host" name="postman_options[<?php esc_attr_e( PostmanOptions::FALLBACK_SMTP_HOSTNAME ); ?>]"
307
- value="<?php esc_attr_e( $host ); ?>" placeholder="Example: smtp.host.com">
308
- </td>
309
- </tr>
310
-
311
- <tr>
312
- <th scope="row"><?php esc_html_e('Mail Server Port', 'post-smtp' ); ?></th>
313
- <?php $port = $this->options->getFallbackPort(); ?>
314
- <td>
315
- <input type="number" id="fallback-smtp-port" name="postman_options[<?php esc_attr_e( PostmanOptions::FALLBACK_SMTP_PORT ); ?>]"
316
- value="<?php esc_attr_e( $port ); ?>" placeholder="Example: 587">
317
- </td>
318
- </tr>
319
-
320
- <tr>
321
- <th scope="row"><?php esc_html_e( 'Security', 'post-smtp' ); ?></th>
322
- <?php
323
- $security_options = array(
324
- 'none' => __( 'None', 'post-smtp' ),
325
- 'ssl' => __( 'SSL', 'post-smtp' ),
326
- 'tls' => __( 'TLS', 'post-smtp' ),
327
- );
328
- ?>
329
- <td>
330
- <select id="fallback-smtp-security" name="postman_options[<?php esc_attr_e( PostmanOptions::FALLBACK_SMTP_SECURITY ); ?>]">
331
- <?php
332
- foreach ( $security_options as $key => $label ) {
333
- $selected = selected( $this->options->getFallbackSecurity(), $key,false );
334
- ?>
335
- <option value="<?php esc_attr_e( $key ); ?>"<?php esc_attr_e( $selected ); ?>><?php echo esc_html( $label ); ?></option>
336
- <?php
337
- }
338
- ?>
339
- </select>
340
- </td>
341
- </tr>
342
-
343
- <tr>
344
- <th scope="row"><?php esc_html_e( 'From Email', 'post-smtp' ); ?></th>
345
- <td>
346
- <input type="email" id="fallback-smtp-from-email"
347
- value="<?php echo esc_attr( $this->options->getFallbackFromEmail() ); ?>"
348
- name="postman_options[<?php echo esc_attr( PostmanOptions::FALLBACK_FROM_EMAIL ); ?>]"
349
- >
350
- <br>
351
- <small><?php esc_html_e( "Use allowed email, for example: If you are using Gmail, type your Gmail adress.", 'post-smtp' ); ?></small>
352
- </td>
353
- </tr>
354
-
355
- <tr valign="">
356
- <th scope="row"><?php esc_html_e( 'Use SMTP Authentication?', 'post-smtp' ); ?></th>
357
- <td>
358
- <label>
359
- <input name="postman_options[<?php echo esc_attr( PostmanOptions::FALLBACK_SMTP_USE_AUTH ); ?>]"
360
- type="radio" value="none"<?php checked( $this->options->getFallbackAuth(), 'none' ); ?>>
361
- <?php esc_html_e( 'No', 'post-smtp' ); ?>
362
- </label>
363
- &nbsp;
364
- <label>
365
- <input name="postman_options[<?php echo esc_attr( PostmanOptions::FALLBACK_SMTP_USE_AUTH ); ?>]"
366
- type="radio" value="login"<?php checked( $this->options->getFallbackAuth(), 'login' ); ?>>
367
- <?php esc_html_e( 'Yes', 'post-smtp' ); ?>
368
- </label>
369
- </td>
370
- </tr>
371
-
372
- <tr>
373
- <th scope="row"><?php esc_html_e('User name', 'post-smtp' ); ?></th>
374
- <td>
375
- <input type="text" id="fallback-smtp-username"
376
- value="<?php echo esc_attr( $this->options->getFallbackUsername() ); ?>"
377
- name="postman_options[<?php echo esc_attr( PostmanOptions::FALLBACK_SMTP_USERNAME ); ?>]"
378
- >
379
- </td>
380
- </tr>
381
-
382
- <tr>
383
- <th scope="row"><?php esc_html_e('Password', 'post-smtp' ); ?></th>
384
- <td>
385
- <input type="password" id="fallback-smtp-password"
386
- value="<?php echo esc_attr( PostmanUtils::obfuscatePassword( $this->options->getFallbackPassword() ) ); ?>"
387
- name="postman_options[<?php echo esc_attr( PostmanOptions::FALLBACK_SMTP_PASSWORD ); ?>]"
388
- >
389
- </td>
390
- </tr>
391
-
392
- </table>
393
- </section>
394
- <!-- Fallback End -->
395
-
396
- <?php
397
- print '<section id="message_config">';
398
- do_settings_sections( PostmanAdminController::MESSAGE_SENDER_OPTIONS );
399
- do_settings_sections( PostmanAdminController::MESSAGE_FROM_OPTIONS );
400
- do_settings_sections( PostmanAdminController::EMAIL_VALIDATION_OPTIONS );
401
- do_settings_sections( PostmanAdminController::MESSAGE_OPTIONS );
402
- do_settings_sections( PostmanAdminController::MESSAGE_HEADERS_OPTIONS );
403
- print '</section>';
404
- print '<section id="logging_config">';
405
- do_settings_sections( PostmanAdminController::LOGGING_OPTIONS );
406
- print '</section>';
407
- /*
408
- * print '<section id="logging_config">';
409
- * do_settings_sections ( PostmanAdminController::MULTISITE_OPTIONS );
410
- * print '</section>';
411
- */
412
- print '<section id="advanced_options_config">';
413
- do_settings_sections( PostmanAdminController::NETWORK_OPTIONS );
414
- do_settings_sections( PostmanAdminController::ADVANCED_OPTIONS );
415
- print '</section>';
416
-
417
- do_action( 'post_smtp_settings_menu' );
418
-
419
- submit_button( 'Save Changes', 'ps-btn-orange' );
420
- print '</form>';
421
- print '</div>';
422
- print '</div>';
423
- }
424
-
425
- /**
426
- */
427
- public function outputWizardContent() {
428
- // Set default values for input fields
429
- $this->options->setMessageSenderEmailIfEmpty( wp_get_current_user()->user_email );
430
- $this->options->setMessageSenderNameIfEmpty( wp_get_current_user()->display_name );
431
-
432
- // construct Wizard
433
- print '<div class="wrap">';
434
-
435
- PostmanViewController::outputChildPageHeader( __( 'Setup Wizard', 'post-smtp' ) );
436
-
437
- print '<form id="postman_wizard" method="post" action="options.php">';
438
-
439
- // account tab
440
- // message tab
441
- printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::PREVENT_MESSAGE_SENDER_EMAIL_OVERRIDE ), esc_attr( $this->options->isPluginSenderEmailEnforced() ) );
442
- printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::PREVENT_MESSAGE_SENDER_NAME_OVERRIDE ), esc_attr( $this->options->isPluginSenderNameEnforced() ) );
443
- printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::REPLY_TO ), esc_attr( $this->options->getReplyTo() ) );
444
- printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::FORCED_TO_RECIPIENTS ), esc_attr( $this->options->getForcedToRecipients() ) );
445
- printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::FORCED_CC_RECIPIENTS ), esc_attr( $this->options->getForcedCcRecipients() ) );
446
- printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::FORCED_BCC_RECIPIENTS ), esc_attr( $this->options->getForcedBccRecipients() ) );
447
- printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::ADDITIONAL_HEADERS ), esc_attr( $this->options->getAdditionalHeaders() ) );
448
- printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::DISABLE_EMAIL_VALIDAITON ), esc_attr( $this->options->isEmailValidationDisabled() ) );
449
-
450
- // logging tab
451
- printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::MAIL_LOG_ENABLED_OPTION ), esc_attr( $this->options->getMailLoggingEnabled() ) );
452
- printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::MAIL_LOG_MAX_ENTRIES ), esc_attr( $this->options->getMailLoggingMaxEntries() ) );
453
- printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::TRANSCRIPT_SIZE ), esc_attr( $this->options->getTranscriptSize() ) );
454
-
455
- // advanced tab
456
- printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::CONNECTION_TIMEOUT ), esc_attr( $this->options->getConnectionTimeout() ) );
457
- printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::READ_TIMEOUT ), esc_attr( $this->options->getReadTimeout() ) );
458
- printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::LOG_LEVEL ), esc_attr( $this->options->getLogLevel() ) );
459
- printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::RUN_MODE ), esc_attr( $this->options->getRunMode() ) );
460
- printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::STEALTH_MODE ), esc_attr( $this->options->isStealthModeEnabled() ) );
461
- printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::TEMPORARY_DIRECTORY ), esc_attr( $this->options->getTempDirectory() ) );
462
-
463
- wp_nonce_field('post-smtp', 'security' );
464
-
465
- // display the setting text
466
- settings_fields( PostmanAdminController::SETTINGS_GROUP_NAME );
467
-
468
- // Wizard Step 0
469
- printf( '<h5>%s</h5>', esc_html_x( 'Import Configuration', 'Wizard Step Title', 'post-smtp' ) );
470
- print '<fieldset>';
471
- printf( '<legend>%s</legend>', esc_html_x( 'Import configuration from another plugin?', 'Wizard Step Title', 'post-smtp' ) );
472
- printf( '<p>%s</p>', esc_html__( 'If you had a working configuration with another Plugin, the Setup Wizard can begin with those settings.', 'post-smtp' ) );
473
-
474
- $style = '';
475
-
476
- if( !$this->importableConfiguration->isImportAvailable() ) {
477
-
478
- $style = 'style="display: none"';
479
-
480
- printf(
481
- '<div class="no-configuration ps-config-bar">
482
- <div class="ps-right">
483
- %s
484
- </div>
485
- <div class="clear"></div>
486
- </div>',
487
- esc_html__( 'No other SMTP plugin configuration has been detected in your installation. You can skip this step.', 'post-smtp' )
488
- );
489
-
490
- }
491
-
492
- printf(
493
- '<div class="input_auth_type">
494
- <div class="ps-socket-wizad-row" %s>
495
- <label>
496
-
497
- <div class="ps-single-socket-outer">
498
- <img src="%s" class="ps-wizard-socket-logo" width="165px">
499
- </div>
500
- <input type="radio" id="import_none" name="input_plugin" value="%s" checked="checked">
501
- <label> %s</label>
502
- </label>',
503
- wp_kses_post( $style ),
504
- esc_url( POST_SMTP_ASSETS . "images/logos/gear.png" ),
505
- 'none',
506
- esc_html__( 'None', 'post-smtp' )
507
- );
508
-
509
- $row = 1;
510
-
511
- if ( $this->importableConfiguration->isImportAvailable() ) {
512
- foreach ( $this->importableConfiguration->getAvailableOptions() as $options ) {
513
- printf(
514
- '<label>
515
- <div class="ps-single-socket-outer">
516
- <img src="%s" class="ps-wizard-socket-logo" width="165px">
517
- </div>
518
- <input type="radio" id="import_none" name="input_plugin" value="%s" checked="checked">
519
- <label> %s</label>
520
- </label>',
521
- esc_url( $options->getPluginLogo() ),
522
- esc_attr( $options->getPluginSlug() ),
523
- esc_html( $options->getPluginName() )
524
- );
525
-
526
- $row++;
527
-
528
- if( $row == 3 ) {
529
- print '</div>';
530
- print '<div class="ps-socket-wizad-row">';
531
- $row = 0;
532
- }
533
- }
534
- }
535
-
536
- print '</div>';
537
- print '</div>';
538
- print '</fieldset>';
539
-
540
- // Wizard Step 1
541
- printf( '<h5>%s</h5>', esc_html_x( 'Sender Details', 'Wizard Step Title', 'post-smtp' ) );
542
- print '<fieldset>';
543
- printf( '<legend>%s</legend>', esc_html_x( 'Who is the mail coming from?', 'Wizard Step Title', 'post-smtp' ) );
544
- printf( '<p>%s</p>', esc_html__( 'Enter the email address and name you\'d like to send mail as.', 'post-smtp' ) );
545
- printf(
546
- '<p>%s <em>%s</em> %s</p>',
547
- esc_html__( 'Please note that to prevent abuse, many email services will ', 'post-smtp' ),
548
- esc_html__( 'not', 'post-smtp' ),
549
- esc_html__( 'let you send from an email address other than the one you authenticate with.', 'post-smtp' )
550
- );
551
-
552
- print( '<div class="ps-ib ps-w-50">' );
553
- printf( '<label for="postman_options[sender_name]">%s</label>', esc_html__( 'Name', 'post-smtp' ) );
554
- print wp_kses_post( $this->settingsRegistry->sender_name_callback() );
555
- print( '</div>' );
556
-
557
- print( '<div class="ps-ib ps-w-50">' );
558
- printf( '<label for="postman_options[sender_email]">%s</label>', esc_html__( 'Email Address', 'post-smtp' ) );
559
- print wp_kses_post( $this->settingsRegistry->from_email_callback() );
560
- print( '</div>' );
561
-
562
- print( '<div class="clear"></div>' );
563
-
564
- print '</fieldset>';
565
-
566
- // Wizard Step 2
567
- printf( '<h5>%s</h5>', esc_html__( 'Outgoing Mail Server Hostname', 'post-smtp' ) );
568
- print '<fieldset>';
569
- foreach ( PostmanTransportRegistry::getInstance()->getTransports() as $transport ) {
570
- $transport->printWizardMailServerHostnameStep();
571
- }
572
- print '</fieldset>';
573
-
574
- // Wizard Step 3
575
- printf( '<h5>%s</h5>', esc_html__( 'Connectivity Test', 'post-smtp' ) );
576
- print '<fieldset>';
577
- printf( '<legend>%s</legend>', esc_html__( 'How will the connection to the mail server be established?', 'post-smtp' ) );
578
- printf( '<p>%s</p>', esc_html__( 'Your connection settings depend on what your email service provider offers, and what your WordPress host allows.', 'post-smtp' ) );
579
- printf( '<p id="connectivity_test_status">%s: <span id="port_test_status">%s</span></p>', esc_html__( 'Connectivity Test', 'post-smtp' ), esc_html_x( 'Ready', 'TCP Port Test Status', 'post-smtp' ) );
580
- printf( '<p class="ajax-loader" style="display:none"><img src="%s"/></p>', esc_url( plugins_url( 'post-smtp/style/ajax-loader.gif' ) ) );
581
- printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]">', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::TRANSPORT_TYPE ) );
582
- printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]">', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::PORT ) );
583
- printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]">', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::SECURITY_TYPE ) );
584
- printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]">', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::AUTHENTICATION_TYPE ) );
585
- print '<legend id="wizard_recommendation"></legend>';
586
- /* Translators: Where %1$s is the socket identifier and %2$s is the authentication type */
587
- printf( '<p class="user_override" style="display:none"><label><span>%s:</span></label> <div id="user_socket_override" class="user_override"></div></p>', esc_html_x( 'Socket', 'A socket is the network term for host and port together', 'post-smtp' ) );
588
- printf( '<p class="user_override" style="display:none"><label><span>%s:</span></label> <div id="user_auth_override" class="user_override"></div></p>', esc_html__( 'Authentication', 'post-smtp' ) );
589
- print ('<p><span id="smtp_mitm" style="display:none; background-color:yellow"></span></p>') ;
590
- $warning = esc_html__( 'Warning', 'post-smtp' );
591
- $clearCredentialsWarning = esc_html__( 'This configuration option will send your authorization credentials in the clear.', 'post-smtp' );
592
- printf(
593
- '<p id="smtp_not_secure" style="display:none"><span style="background-color:yellow">%s: %s</span></p>',
594
- esc_html( $warning ),
595
- esc_html( $clearCredentialsWarning )
596
- );
597
- print '</fieldset>';
598
-
599
- // Wizard Step 4
600
- printf( '<h5>%s</h5>', esc_html__( 'Authentication', 'post-smtp' ) );
601
- print '<fieldset>';
602
- printf( '<legend>%s</legend>', esc_html__( 'How will you prove your identity to the mail server?', 'post-smtp' ) );
603
- foreach ( PostmanTransportRegistry::getInstance()->getTransports() as $transport ) {
604
- $transport->printWizardAuthenticationStep();
605
- }
606
- print '</fieldset>';
607
-
608
- // Wizard Step 5 - Notificiations
609
- printf( '<h5>%s</h5>', esc_html__( 'Notifications', 'post-smtp' ) );
610
- print '<fieldset>';
611
- printf( '<legend>%s</legend>', esc_html__( 'Select a notify service to notify you when an email is failed to delivered.', 'post-smtp' ) );
612
-
613
- ?>
614
- <select id="input_notification_service" class="input_notification_service" name="postman_options[notification_service]">
615
- <option value="default">Email</option>
616
- <option value="pushover">Pushover</option>
617
- <option value="slack">Slack</option>
618
- </select>
619
- <div id="pushover_cred" style="display: none;">
620
- <h2><?php esc_html_e( 'Pushover Credentials', 'post-smtp' ); ?></h2>
621
- <table class="form-table">
622
- <tbody>
623
- <tr>
624
- <th scope="row"><?php esc_html_e( 'Pushover User Key', 'post-smtp' ); ?></th>
625
- <td>
626
- <input type="password" id="pushover_user" name="postman_options[pushover_user]" value="">
627
- </td>
628
- </tr>
629
- <tr>
630
- <th scope="row"><?php esc_html_e( 'Pushover App Token', 'post-smtp' ); ?></th>
631
- <td>
632
- <input type="password" id="pushover_token" name="postman_options[pushover_token]" value="">
633
- </td>
634
- </tr>
635
- </tbody>
636
- </table>
637
- </div>
638
- <div id="slack_cred" style="display: none;">
639
- <h2><?php esc_html_e( 'Slack Credentials', 'post-smtp' ); ?></h2>
640
- <table class="form-table">
641
- <tbody>
642
- <tr>
643
- <th scope="row"><?php esc_html_e( 'Slack webhook', 'post-smtp' ); ?></th>
644
- <td>
645
- <input type="password" id="slack_token" name="postman_options[slack_token]" value="">
646
- <a target="_blank" class="" href="https://slack.postmansmtp.com/">
647
- <?php esc_html_e( 'Get your webhook URL here.', 'post-smtp' ); ?>
648
- </a>
649
- </td>
650
- </tr>
651
- </tbody>
652
- </table>
653
- </div>
654
-
655
- <div id="use-chrome-extension">
656
- <h2><?php esc_html_e( 'Push To Chrome Extension', 'post-smtp' ); ?></h2>
657
- <table class="form-table">
658
- <tbody>
659
- <tr>
660
- <th scope="row"><?php esc_html_e( 'This is an extra notification to the selection above', 'post-smtp' ); ?></th>
661
- <td>
662
- <input type="checkbox" id="notification_use_chrome" name="postman_options[notification_use_chrome]">
663
- <a target="_blank" class="" href="https://chrome.google.com/webstore/detail/npklmbkpbknkmbohdbpikeidiaekjoch">
664
- <?php esc_html_e( 'You can download the chrome extension here (if link not available, check later).', 'post-smtp' ); ?>
665
- </a>
666
- </td>
667
- </tr>
668
- <tr>
669
- <th scope="row"><?php esc_html_e( 'Your UID as you see in the extension.', 'post-smtp' ); ?></th>
670
- <td>
671
- <input type="password" id="notification_chrome_uid" name="postman_options[notification_chrome_uid]" value="">
672
- </td>
673
- </tr>
674
- </tbody>
675
- </table>
676
- </div>
677
-
678
- <?php
679
- print '</fieldset>';
680
-
681
- // Wizard Step 6
682
- printf( '<h5>%s</h5>', esc_html_x( 'Finish', 'The final step of the Wizard', 'post-smtp' ) );
683
- print '<fieldset>';
684
- printf( '<legend>%s</legend>', esc_html_x( 'You\'re Done!', 'Wizard Step Title', 'post-smtp' ) );
685
- print '<section>';
686
- printf( '<p>%s</p>', esc_html__( 'Click Finish to save these settings, then:', 'post-smtp' ) );
687
- print '<ul style="margin-left: 20px">';
688
- printf( '<li class="wizard-auth-oauth2">%s</li>', esc_html__( 'Grant permission with the Email Provider for Postman to send email and', 'post-smtp' ) );
689
- printf( '<li>%s</li>', esc_html__( 'Send yourself a Test Email to make sure everything is working!', 'post-smtp' ) );
690
- print '</ul>';
691
-
692
- // Get PHPmailer recommendation
693
- Postman::getMailerTypeRecommend();
694
-
695
- $in_wizard = true;
696
-
697
- print '</section>';
698
- print '</fieldset>';
699
- print '</form>';
700
- print '</div>';
701
- }
702
- }
703
-
704
- /**
705
- *
706
- * @author jasonhendriks
707
- */
708
- class PostmanGetHostnameByEmailAjaxController extends PostmanAbstractAjaxHandler {
709
- const IS_GOOGLE_PARAMETER = 'is_google';
710
- function __construct() {
711
- parent::__construct();
712
- PostmanUtils::registerAjaxHandler( 'postman_check_email', $this, 'getAjaxHostnameByEmail' );
713
- }
714
- /**
715
- * This Ajax function retrieves the smtp hostname for a give e-mail address
716
- */
717
- function getAjaxHostnameByEmail() {
718
-
719
- check_admin_referer('post-smtp', 'security');
720
-
721
- if( !current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_NAME ) ) {
722
- wp_send_json_error(
723
- array(
724
- 'Message' => 'Unauthorized.'
725
- ),
726
- 401
727
- );
728
- }
729
-
730
- $goDaddyHostDetected = $this->getBooleanRequestParameter( 'go_daddy' );
731
- $email = $this->getRequestParameter( 'email' );
732
- $d = new PostmanSmtpDiscovery( $email );
733
- $smtp = $d->getSmtpServer();
734
- $this->logger->debug( 'given email ' . $email . ', smtp server is ' . $smtp );
735
- $this->logger->trace( $d );
736
- if ( $goDaddyHostDetected && ! $d->isGoogle ) {
737
- // override with the GoDaddy SMTP server
738
- $smtp = 'relay-hosting.secureserver.net';
739
- $this->logger->debug( 'detected GoDaddy SMTP server, smtp server is ' . $smtp );
740
- }
741
- $response = array(
742
- 'hostname' => $smtp,
743
- self::IS_GOOGLE_PARAMETER => $d->isGoogle,
744
- 'is_go_daddy' => $d->isGoDaddy,
745
- 'is_well_known' => $d->isWellKnownDomain,
746
- );
747
- $this->logger->trace( $response );
748
- wp_send_json_success( $response );
749
- }
750
- }
751
- class PostmanManageConfigurationAjaxHandler extends PostmanAbstractAjaxHandler {
752
- function __construct() {
753
- parent::__construct();
754
- PostmanUtils::registerAjaxHandler( 'manual_config', $this, 'getManualConfigurationViaAjax' );
755
- PostmanUtils::registerAjaxHandler( 'get_wizard_configuration_options', $this, 'getWizardConfigurationViaAjax' );
756
- }
757
-
758
- /**
759
- * Handle a Advanced Configuration request with Ajax
760
- *
761
- * @throws Exception
762
- */
763
- function getManualConfigurationViaAjax() {
764
-
765
- check_admin_referer('post-smtp', 'security');
766
-
767
- if( !current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_NAME ) ) {
768
- wp_send_json_error(
769
- array(
770
- 'Message' => 'Unauthorized.'
771
- ),
772
- 401
773
- );
774
- }
775
-
776
- $queryTransportType = $this->getTransportTypeFromRequest();
777
- $queryAuthType = $this->getAuthenticationTypeFromRequest();
778
- $queryHostname = $this->getHostnameFromRequest();
779
-
780
- // the outgoing server hostname is only required for the SMTP Transport
781
- // the Gmail API transport doesn't use an SMTP server
782
- $transport = PostmanTransportRegistry::getInstance()->getTransport( $queryTransportType );
783
- if ( ! $transport ) {
784
- throw new Exception( 'Unable to find transport ' . $queryTransportType );
785
- }
786
-
787
- // create the response
788
- $response = $transport->populateConfiguration( $queryHostname );
789
- $response ['referer'] = 'manual_config';
790
-
791
- // set the display_auth to oauth2 if the transport needs it
792
- if ( $transport->isOAuthUsed( $queryAuthType ) ) {
793
- $response ['display_auth'] = 'oauth2';
794
- $this->logger->debug( 'ajaxRedirectUrl answer display_auth:' . $response ['display_auth'] );
795
- }
796
- $this->logger->trace( $response );
797
- wp_send_json_success( $response );
798
- }
799
-
800
- /**
801
- * Once the Port Tests have run, the results are analyzed.
802
- * The Transport place bids on the sockets and highest bid becomes the recommended
803
- * The UI response is built so the user may choose a different socket with different options.
804
- */
805
- function getWizardConfigurationViaAjax() {
806
-
807
- check_admin_referer('post-smtp', 'security');
808
-
809
- if( !current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_NAME ) ) {
810
- wp_send_json_error(
811
- array(
812
- 'Message' => 'Unauthorized.'
813
- ),
814
- 401
815
- );
816
- }
817
-
818
- $this->logger->debug( 'in getWizardConfiguration' );
819
- $originalSmtpServer = $this->getRequestParameter( 'original_smtp_server' );
820
- $queryHostData = $this->getHostDataFromRequest();
821
- $sockets = array();
822
- foreach ( $queryHostData as $id => $datum ) {
823
- array_push( $sockets, new PostmanWizardSocket( $datum ) );
824
- }
825
-
826
- $this->logger->error( $sockets );
827
- $userPortOverride = $this->getUserPortOverride();
828
- $userAuthOverride = $this->getUserAuthOverride();
829
-
830
- // determine a configuration recommendation
831
- $winningRecommendation = $this->getWinningRecommendation( $sockets, $userPortOverride, $userAuthOverride, $originalSmtpServer );
832
- if ( $this->logger->isTrace() ) {
833
- $this->logger->trace( 'winning recommendation:' );
834
- $this->logger->trace( $winningRecommendation );
835
- }
836
-
837
- // create the reponse
838
- $response = array();
839
- $configuration = array();
840
- $response ['referer'] = 'wizard';
841
- if ( isset( $userPortOverride ) || isset( $userAuthOverride ) ) {
842
- $configuration ['user_override'] = true;
843
- }
844
-
845
- if ( isset( $winningRecommendation ) ) {
846
-
847
- // create an appropriate (theoretical) transport
848
- $transport = PostmanTransportRegistry::getInstance()->getTransport( $winningRecommendation ['transport'] );
849
-
850
- // create user override menu
851
- $overrideMenu = $this->createOverrideMenus( $sockets, $winningRecommendation, $userPortOverride, $userAuthOverride );
852
- if ( $this->logger->isTrace() ) {
853
- $this->logger->trace( 'override menu:' );
854
- $this->logger->trace( $overrideMenu );
855
- }
856
-
857
- $queryHostName = $winningRecommendation ['hostname'];
858
- if ( $this->logger->isDebug() ) {
859
- $this->logger->debug( 'Getting scribe for ' . $queryHostName );
860
- }
861
- $generalConfig1 = $transport->populateConfiguration( $queryHostName );
862
- $generalConfig2 = $transport->populateConfigurationFromRecommendation( $winningRecommendation );
863
- $configuration = array_merge( $configuration, $generalConfig1, $generalConfig2 );
864
- $response ['override_menu'] = $overrideMenu;
865
- $response ['configuration'] = $configuration;
866
- if ( $this->logger->isTrace() ) {
867
- $this->logger->trace( 'configuration:' );
868
- $this->logger->trace( $configuration );
869
- $this->logger->trace( 'response:' );
870
- $this->logger->trace( $response );
871
- }
872
- wp_send_json_success( $response );
873
- } else {
874
- /* translators: where %s is the URL to the Connectivity Test page */
875
- $configuration ['message'] = sprintf( __( 'Postman can\'t find any way to send mail on your system. Run a <a href="%s">connectivity test</a>.', 'post-smtp' ), PostmanViewController::getPageUrl( PostmanConnectivityTestController::PORT_TEST_SLUG ) );
876
- $response ['configuration'] = $configuration;
877
- if ( $this->logger->isTrace() ) {
878
- $this->logger->trace( 'configuration:' );
879
- $this->logger->trace( $configuration );
880
- }
881
- wp_send_json_error( $response );
882
- }
883
- }
884
-
885
- /**
886
- * // for each successful host/port combination
887
- * // ask a transport if they support it, and if they do at what priority is it
888
- * // configure for the highest priority you find
889
- *
890
- * @param mixed $queryHostData
891
- * @return mixed
892
- */
893
- private function getWinningRecommendation( $sockets, $userSocketOverride, $userAuthOverride, $originalSmtpServer ) {
894
-
895
- foreach ( $sockets as $socket ) {
896
- $winningRecommendation = $this->getWin( $socket, $userSocketOverride, $userAuthOverride, $originalSmtpServer );
897
- $this->logger->error( $socket->label );
898
- }
899
-
900
- return $winningRecommendation;
901
- }
902
-
903
- /**
904
- *
905
- * @param PostmanWizardSocket $socket
906
- * @param mixed $userSocketOverride
907
- * @param mixed $userAuthOverride
908
- * @param mixed $originalSmtpServer
909
- * @return mixed
910
- */
911
- private function getWin( PostmanWizardSocket $socket, $userSocketOverride, $userAuthOverride, $originalSmtpServer ) {
912
- static $recommendationPriority = - 1;
913
- static $winningRecommendation = null;
914
- $available = $socket->success;
915
- if ( $available ) {
916
- $this->logger->debug( sprintf( 'Asking for judgement on %s:%s', $socket->hostname, $socket->port ) );
917
- $recommendation = PostmanTransportRegistry::getInstance()->getRecommendation( $socket, $userAuthOverride, $originalSmtpServer );
918
- $recommendationId = sprintf( '%s_%s', $socket->hostname, $socket->port );
919
- $recommendation ['id'] = $recommendationId;
920
- $this->logger->debug( sprintf( 'Got a recommendation: [%d] %s', $recommendation ['priority'], $recommendationId ) );
921
- if ( isset( $userSocketOverride ) ) {
922
- if ( $recommendationId == $userSocketOverride ) {
923
- $winningRecommendation = $recommendation;
924
- $this->logger->debug( sprintf( 'User chosen socket %s is the winner', $recommendationId ) );
925
- }
926
- } elseif ( $recommendation && $recommendation ['priority'] > $recommendationPriority ) {
927
- $recommendationPriority = $recommendation ['priority'];
928
- $winningRecommendation = $recommendation;
929
- }
930
- $socket->label = $recommendation ['label'];
931
- }
932
-
933
- return $winningRecommendation;
934
- }
935
-
936
- /**
937
- *
938
- * @param mixed $queryHostData
939
- * @return multitype:
940
- */
941
- private function createOverrideMenus( $sockets, $winningRecommendation, $userSocketOverride, $userAuthOverride ) {
942
-
943
- $overrideMenu = array();
944
- $last_items = array();
945
-
946
- foreach ( $sockets as $socket ) {
947
-
948
- $overrideItem = $this->createOverrideMenu( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
949
- if ( $overrideItem != null ) {
950
-
951
- $transport = PostmanTransportRegistry::getInstance()->getTransport( $socket->transport );
952
-
953
- //If class has constant
954
- if( defined( get_class( $transport ) . "::PRIORITY" ) ) {
955
-
956
- $priority = $transport::PRIORITY;
957
- $overrideMenu[$priority] = $overrideItem;
958
-
959
- }
960
- else {
961
-
962
- $last_items[] = $overrideItem;
963
-
964
- }
965
-
966
- }
967
-
968
- }
969
-
970
- //Sort in DESC order
971
- krsort( $overrideMenu );
972
-
973
- //Start Placing sockets in last, because they don't have there own priority.
974
- foreach( $last_items as $item ) {
975
-
976
- $overrideMenu[] = $item;
977
-
978
- }
979
-
980
- $menu = array();
981
- foreach ( $overrideMenu as $key ) {
982
- array_push( $menu, $key );
983
- }
984
-
985
- return $menu;
986
-
987
- }
988
-
989
- /**
990
- *
991
- * @param PostmanWizardSocket $socket
992
- * @param mixed $winningRecommendation
993
- * @param mixed $userSocketOverride
994
- * @param mixed $userAuthOverride
995
- */
996
- private function createOverrideMenu( PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride ) {
997
- if ( $socket->success ) {
998
- $transport = PostmanTransportRegistry::getInstance()->getTransport( $socket->transport );
999
- $this->logger->debug( sprintf( 'Transport %s is building the override menu for socket', $transport->getSlug() ) );
1000
- $overrideItem = $transport->createOverrideMenu( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
1001
- return $overrideItem;
1002
- }
1003
- return null;
1004
- }
1005
-
1006
- /**
1007
- */
1008
- private function getTransportTypeFromRequest() {
1009
- return $this->getRequestParameter( 'transport' );
1010
- }
1011
-
1012
- /**
1013
- */
1014
- private function getHostnameFromRequest() {
1015
- return $this->getRequestParameter( 'hostname' );
1016
- }
1017
-
1018
- /**
1019
- */
1020
- private function getAuthenticationTypeFromRequest() {
1021
- return $this->getRequestParameter( 'auth_type' );
1022
- }
1023
-
1024
- /**
1025
- */
1026
- private function getHostDataFromRequest() {
1027
- return $this->getRequestParameter( 'host_data' );
1028
- }
1029
-
1030
- /**
1031
- */
1032
- private function getUserPortOverride() {
1033
- return $this->getRequestParameter( 'user_port_override' );
1034
- }
1035
-
1036
- /**
1037
- */
1038
- private function getUserAuthOverride() {
1039
- return $this->getRequestParameter( 'user_auth_override' );
1040
- }
1041
- }
1042
- class PostmanImportConfigurationAjaxController extends PostmanAbstractAjaxHandler {
1043
- private $options;
1044
- /**
1045
- * Constructor
1046
- *
1047
- * @param PostmanOptions $options
1048
- */
1049
- function __construct( PostmanOptions $options ) {
1050
- parent::__construct();
1051
- $this->options = $options;
1052
- PostmanUtils::registerAjaxHandler( 'import_configuration', $this, 'getConfigurationFromExternalPluginViaAjax' );
1053
- }
1054
-
1055
- /**
1056
- * This function extracts configuration details form a competing SMTP plugin
1057
- * and pushes them into the Postman configuration screen.
1058
- */
1059
- function getConfigurationFromExternalPluginViaAjax() {
1060
-
1061
- check_admin_referer('post-smtp', 'security');
1062
-
1063
- if( !current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_NAME ) ) {
1064
- wp_send_json_error(
1065
- array(
1066
- 'Message' => 'Unauthorized.'
1067
- ),
1068
- 401
1069
- );
1070
- }
1071
-
1072
- $importableConfiguration = new PostmanImportableConfiguration();
1073
- $plugin = $this->getRequestParameter( 'plugin' );
1074
- $this->logger->debug( 'Looking for config=' . $plugin );
1075
- foreach ( $importableConfiguration->getAvailableOptions() as $this->options ) {
1076
- if ( $this->options->getPluginSlug() == $plugin ) {
1077
- $this->logger->debug( 'Sending configuration response' );
1078
- $response = array(
1079
- PostmanOptions::MESSAGE_SENDER_EMAIL => $this->options->getMessageSenderEmail(),
1080
- PostmanOptions::MESSAGE_SENDER_NAME => $this->options->getMessageSenderName(),
1081
- PostmanOptions::HOSTNAME => $this->options->getHostname(),
1082
- PostmanOptions::PORT => $this->options->getPort(),
1083
- PostmanOptions::AUTHENTICATION_TYPE => $this->options->getAuthenticationType(),
1084
- PostmanOptions::SECURITY_TYPE => $this->options->getEncryptionType(),
1085
- PostmanOptions::BASIC_AUTH_USERNAME => $this->options->getUsername(),
1086
- PostmanOptions::BASIC_AUTH_PASSWORD => $this->options->getPassword(),
1087
- 'success' => true,
1088
- );
1089
- break;
1090
- }
1091
- }
1092
- if ( ! isset( $response ) ) {
1093
- $response = array(
1094
- 'success' => false,
1095
- );
1096
- }
1097
- wp_send_json( $response );
1098
- }
1099
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ require_once( 'PostmanRegisterConfigurationSettings.php' );
7
+ class PostmanConfigurationController {
8
+ const CONFIGURATION_SLUG = 'postman/configuration';
9
+ const CONFIGURATION_WIZARD_SLUG = 'postman/configuration_wizard';
10
+
11
+ // logging
12
+ private $logger;
13
+ private $options;
14
+ private $settingsRegistry;
15
+
16
+ // Holds the values to be used in the fields callbacks
17
+ private $rootPluginFilenameAndPath;
18
+
19
+ private $importableConfiguration;
20
+
21
+ /**
22
+ * Constructor
23
+ *
24
+ * @param mixed $rootPluginFilenameAndPath
25
+ */
26
+ public function __construct( $rootPluginFilenameAndPath ) {
27
+
28
+ assert( ! empty( $rootPluginFilenameAndPath ) );
29
+ assert( PostmanUtils::isAdmin() );
30
+ assert( is_admin() );
31
+
32
+ $this->logger = new PostmanLogger( get_class( $this ) );
33
+ $this->rootPluginFilenameAndPath = $rootPluginFilenameAndPath;
34
+ $this->options = PostmanOptions::getInstance();
35
+ $this->settingsRegistry = new PostmanSettingsRegistry();
36
+
37
+ PostmanUtils::registerAdminMenu( $this, 'addSetupWizardSubmenu' );
38
+
39
+ // hook on the init event
40
+ add_action( 'init', array(
41
+ $this,
42
+ 'on_init',
43
+ ) );
44
+
45
+ // initialize the scripts, stylesheets and form fields
46
+ add_action( 'admin_init', array(
47
+ $this,
48
+ 'on_admin_init',
49
+ ) );
50
+
51
+ add_action( 'admin_menu', array( $this, 'add_submenu_page' ), 21 );
52
+
53
+ }
54
+
55
+ /**
56
+ * Functions to execute on the init event
57
+ *
58
+ * "Typically used by plugins to initialize. The current user is already authenticated by this time."
59
+ * ref: http://codex.wordpress.org/Plugin_API/Action_Reference#Actions_Run_During_a_Typical_Request
60
+ */
61
+ public function on_init() {
62
+ // register Ajax handlers
63
+ new PostmanGetHostnameByEmailAjaxController();
64
+ new PostmanManageConfigurationAjaxHandler();
65
+ new PostmanImportConfigurationAjaxController( $this->options );
66
+ }
67
+
68
+ /**
69
+ * Fires on the admin_init method
70
+ */
71
+ public function on_admin_init() {
72
+ $this->registerStylesAndScripts();
73
+ $this->settingsRegistry->on_admin_init();
74
+ }
75
+
76
+ /**
77
+ * Register and add settings
78
+ */
79
+ private function registerStylesAndScripts() {
80
+ if ( $this->logger->isTrace() ) {
81
+ $this->logger->trace( 'registerStylesAndScripts()' );
82
+ }
83
+ // register the stylesheet and javascript external resources
84
+ $pluginData = apply_filters( 'postman_get_plugin_metadata', null );
85
+
86
+ wp_register_script( 'postman_manual_config_script', plugins_url( 'Postman/Postman-Configuration/postman_manual_config.js', $this->rootPluginFilenameAndPath ), array(
87
+ PostmanViewController::JQUERY_SCRIPT,
88
+ 'jquery-ui-core',
89
+ 'jquery-ui-tabs',
90
+ 'jquery_validation',
91
+ PostmanViewController::POSTMAN_SCRIPT,
92
+ ), $pluginData ['version'] );
93
+
94
+ wp_register_script( 'postman_wizard_script', plugins_url( 'Postman/Postman-Configuration/postman_wizard.js', $this->rootPluginFilenameAndPath ), array(
95
+ PostmanViewController::JQUERY_SCRIPT,
96
+ 'jquery_validation',
97
+ 'jquery_steps_script',
98
+ PostmanViewController::POSTMAN_SCRIPT,
99
+ 'sprintf',
100
+ ), $pluginData ['version'] );
101
+ }
102
+
103
+ /**
104
+ */
105
+ private function addLocalizeScriptsToPage() {
106
+
107
+ // the transport modules scripts
108
+ foreach ( PostmanTransportRegistry::getInstance()->getTransports() as $transport ) {
109
+ $transport->enqueueScript();
110
+ }
111
+
112
+ // we need data from port test
113
+ PostmanConnectivityTestController::addLocalizeScriptForPortTest();
114
+
115
+ }
116
+
117
+ /**
118
+ * Adds sub menu page `Settings`
119
+ *
120
+ * @since 2.1
121
+ * @version 1.0
122
+ */
123
+ public function add_submenu_page() {
124
+
125
+ // only do this for administrators
126
+ if ( PostmanUtils::isAdmin() ) {
127
+
128
+ $this->logger->trace( 'created PostmanSettings admin menu item' );
129
+
130
+ $page = add_submenu_page(
131
+ PostmanViewController::POSTMAN_MENU_SLUG,
132
+ sprintf( __( '%s Setup', 'post-smtp' ), __( 'Postman SMTP', 'post-smtp' ) ),
133
+ __( 'Settings', 'post-smtp' ),
134
+ Postman::MANAGE_POSTMAN_CAPABILITY_NAME,
135
+ PostmanConfigurationController::CONFIGURATION_SLUG,
136
+ array(
137
+ $this,
138
+ 'outputManualConfigurationContent',
139
+ ) );
140
+
141
+ // When the plugin options page is loaded, also load the stylesheet
142
+ add_action( 'admin_print_styles-' . $page, array( $this, 'enqueueConfigurationResources' ) );
143
+
144
+ }
145
+
146
+ }
147
+
148
+ /**
149
+ */
150
+ function enqueueConfigurationResources() {
151
+ $this->addLocalizeScriptsToPage();
152
+ wp_enqueue_style( 'jquery_ui_style' );
153
+ wp_enqueue_style( PostmanViewController::POSTMAN_STYLE );
154
+ wp_enqueue_script( 'postman_manual_config_script' );
155
+ }
156
+
157
+ /**
158
+ * Register the Setup Wizard screen
159
+ */
160
+ public function addSetupWizardSubmenu() {
161
+ $page = add_submenu_page( null, sprintf( __( '%s Setup', 'post-smtp' ), __( 'Postman SMTP', 'post-smtp' ) ), __( 'Postman SMTP', 'post-smtp' ), Postman::MANAGE_POSTMAN_CAPABILITY_NAME, PostmanConfigurationController::CONFIGURATION_WIZARD_SLUG, array(
162
+ $this,
163
+ 'outputWizardContent',
164
+ ) );
165
+ // When the plugin options page is loaded, also load the stylesheet
166
+ add_action( 'admin_print_styles-' . $page, array(
167
+ $this,
168
+ 'enqueueWizardResources',
169
+ ) );
170
+ }
171
+
172
+ /**
173
+ */
174
+ function enqueueWizardResources() {
175
+ $this->addLocalizeScriptsToPage();
176
+ $this->importableConfiguration = new PostmanImportableConfiguration();
177
+ $startPage = 1;
178
+ if ( $this->importableConfiguration->isImportAvailable() ) {
179
+ $startPage = 0;
180
+ }
181
+ wp_localize_script( PostmanViewController::POSTMAN_SCRIPT, 'postman_setup_wizard', array(
182
+ 'start_page' => $startPage,
183
+ ) );
184
+ wp_enqueue_style( 'jquery_steps_style' );
185
+ wp_enqueue_style( PostmanViewController::POSTMAN_STYLE );
186
+ wp_enqueue_script( 'postman_wizard_script' );
187
+
188
+ wp_localize_script( 'postman_wizard_script', 'postman',
189
+ array(
190
+ 'assets' => POST_SMTP_ASSETS
191
+ )
192
+ );
193
+
194
+ //wp_localize_script( PostmanViewController::POSTMAN_SCRIPT, '$jq', 'jQuery.noConflict(true)' );
195
+ $shortLocale = substr( get_locale(), 0, 2 );
196
+ if ( $shortLocale != 'en' ) {
197
+ $url = plugins_url( sprintf( 'script/jquery-validate/localization/messages_%s.js', $shortLocale ), $this->rootPluginFilenameAndPath );
198
+ wp_enqueue_script( sprintf( 'jquery-validation-locale-%s', $shortLocale ), $url, array(), POST_SMTP_VER );
199
+ }
200
+ }
201
+
202
+ /**
203
+ */
204
+ public function outputManualConfigurationContent() {
205
+ print '<div class="wrap">';
206
+
207
+ PostmanViewController::outputChildPageHeader( __( 'Settings', 'post-smtp' ), 'advanced_config' );
208
+
209
+ $config_tabs = apply_filters( 'post_smtp_admin_tabs', array(
210
+ 'account_config' => __( 'Account', 'post-smtp' ),
211
+ 'fallback' => __( 'Fallback', 'post-smtp' ),
212
+ 'message_config' => __( 'Message', 'post-smtp' ),
213
+ 'logging_config' => __( 'Logging', 'post-smtp' ),
214
+ 'advanced_options_config' => __( 'Advanced', 'post-smtp' ),
215
+ ) );
216
+
217
+ print '<div id="config_tabs"><ul>';
218
+
219
+ foreach ( $config_tabs as $slug => $tab ) :
220
+ printf( '<li><a href="#%s">%s</a></li>', esc_attr( $slug ), esc_html( $tab ) );
221
+ endforeach;
222
+
223
+ print '</ul>';
224
+
225
+ print '<form method="post" action="options.php">';
226
+
227
+ wp_nonce_field('post-smtp', 'security');
228
+
229
+ // This prints out all hidden setting fields
230
+ settings_fields( PostmanAdminController::SETTINGS_GROUP_NAME );
231
+
232
+ // account_config
233
+ print '<section id="account_config">';
234
+ if ( sizeof( PostmanTransportRegistry::getInstance()->getTransports() ) > 1 ) {
235
+ do_settings_sections( 'transport_options' );
236
+ }
237
+ else {
238
+ printf(
239
+ '<input id="input_%2$s" type="hidden" name="%1$s[%2$s]" value="%3$s"/>',
240
+ esc_attr( PostmanOptions::POSTMAN_OPTIONS ),
241
+ esc_attr( PostmanOptions::TRANSPORT_TYPE ),
242
+ esc_attr( PostmanSmtpModuleTransport::SLUG )
243
+ );
244
+ }
245
+ print '<div id="smtp_config" class="transport_setting">';
246
+ do_settings_sections( PostmanAdminController::SMTP_OPTIONS );
247
+ print '</div>';
248
+ print '<div id="password_settings" class="authentication_setting non-oauth2">';
249
+ do_settings_sections( PostmanAdminController::BASIC_AUTH_OPTIONS );
250
+ print '</div>';
251
+ print '<div id="oauth_settings" class="authentication_setting non-basic">';
252
+ do_settings_sections( PostmanAdminController::OAUTH_AUTH_OPTIONS );
253
+ print '</div>';
254
+ print '<div id="mandrill_settings" class="authentication_setting non-basic non-oauth2">';
255
+ do_settings_sections( PostmanMandrillTransport::MANDRILL_AUTH_OPTIONS );
256
+ print '</div>';
257
+ print '<div id="sendgrid_settings" class="authentication_setting non-basic non-oauth2">';
258
+ do_settings_sections( PostmanSendGridTransport::SENDGRID_AUTH_OPTIONS );
259
+ print '</div>';
260
+ print '<div id="mailgun_settings" class="authentication_setting non-basic non-oauth2">';
261
+ do_settings_sections( PostmanMailgunTransport::MAILGUN_AUTH_OPTIONS );
262
+ print '</div>';
263
+ print '<div id="sendinblue_settings" class="authentication_setting non-basic non-oauth2">';
264
+ do_settings_sections( PostmanSendinblueTransport::SENDINBLUE_AUTH_OPTIONS );
265
+ print '</div>';
266
+ print '<div id="postmark_settings" class="authentication_setting non-basic non-oauth2">';
267
+ do_settings_sections( PostmanPostmarkTransport::POSTMARK_AUTH_OPTIONS );
268
+ print '</div>';
269
+ print '<div id="sparkpost_settings" class="authentication_setting non-basic non-oauth2">';
270
+ do_settings_sections( PostmanSparkPostTransport::SPARKPOST_AUTH_OPTIONS );
271
+ print '</div>';
272
+
273
+ do_action( 'post_smtp_settings_sections' );
274
+
275
+ print '</section>';
276
+ // end account config
277
+ ?>
278
+
279
+ <!-- Fallback Start -->
280
+ <section id="fallback">
281
+ <h2><?php esc_html_e( 'Failed emails fallback', 'post-smtp' ); ?></h2>
282
+ <p><?php esc_html_e( 'By enable this option, if your email is fail to send Post SMTP will try to use the SMTP service you define here.', 'post-smtp' ); ?></p>
283
+ <table class="form-table">
284
+ <tr valign="">
285
+ <th scope="row"><?php esc_html_e( 'Use Fallback?', 'post-smtp' ); ?></th>
286
+ <td>
287
+ <label>
288
+ <input name="postman_options[<?php esc_attr_e( PostmanOptions::FALLBACK_SMTP_ENABLED ); ?>]" type="radio"
289
+ value="no"<?php echo checked( $this->options->getFallbackIsEnabled(), 'no' ); ?>>
290
+ <?php esc_html_e( 'No', 'post-smtp' ); ?>
291
+ </label>
292
+ &nbsp;
293
+ <label>
294
+ <?php $checked = checked( $this->options->getFallbackIsEnabled(), 'yes', false ); ?>
295
+ <input name="postman_options[<?php esc_attr_e( PostmanOptions::FALLBACK_SMTP_ENABLED ); ?>]" type="radio"
296
+ value="yes"<?php echo checked( $this->options->getFallbackIsEnabled(), 'yes' ); ?>>
297
+ <?php esc_html_e( 'Yes', 'post-smtp' ); ?>
298
+ </label>
299
+ </td>
300
+ </tr>
301
+
302
+ <tr>
303
+ <th scope="row"><?php esc_html_e('Outgoing Mail Server', 'post-smtp' ); ?></th>
304
+ <?php $host = $this->options->getFallbackHostname(); ?>
305
+ <td>
306
+ <input type="text" id="fallback-smtp-host" name="postman_options[<?php esc_attr_e( PostmanOptions::FALLBACK_SMTP_HOSTNAME ); ?>]"
307
+ value="<?php esc_attr_e( $host ); ?>" placeholder="Example: smtp.host.com">
308
+ </td>
309
+ </tr>
310
+
311
+ <tr>
312
+ <th scope="row"><?php esc_html_e('Mail Server Port', 'post-smtp' ); ?></th>
313
+ <?php $port = $this->options->getFallbackPort(); ?>
314
+ <td>
315
+ <input type="number" id="fallback-smtp-port" name="postman_options[<?php esc_attr_e( PostmanOptions::FALLBACK_SMTP_PORT ); ?>]"
316
+ value="<?php esc_attr_e( $port ); ?>" placeholder="Example: 587">
317
+ </td>
318
+ </tr>
319
+
320
+ <tr>
321
+ <th scope="row"><?php esc_html_e( 'Security', 'post-smtp' ); ?></th>
322
+ <?php
323
+ $security_options = array(
324
+ 'none' => __( 'None', 'post-smtp' ),
325
+ 'ssl' => __( 'SSL', 'post-smtp' ),
326
+ 'tls' => __( 'TLS', 'post-smtp' ),
327
+ );
328
+ ?>
329
+ <td>
330
+ <select id="fallback-smtp-security" name="postman_options[<?php esc_attr_e( PostmanOptions::FALLBACK_SMTP_SECURITY ); ?>]">
331
+ <?php
332
+ foreach ( $security_options as $key => $label ) {
333
+ $selected = selected( $this->options->getFallbackSecurity(), $key,false );
334
+ ?>
335
+ <option value="<?php esc_attr_e( $key ); ?>"<?php esc_attr_e( $selected ); ?>><?php echo esc_html( $label ); ?></option>
336
+ <?php
337
+ }
338
+ ?>
339
+ </select>
340
+ </td>
341
+ </tr>
342
+
343
+ <tr>
344
+ <th scope="row"><?php esc_html_e( 'From Email', 'post-smtp' ); ?></th>
345
+ <td>
346
+ <input type="email" id="fallback-smtp-from-email"
347
+ value="<?php echo esc_attr( $this->options->getFallbackFromEmail() ); ?>"
348
+ name="postman_options[<?php echo esc_attr( PostmanOptions::FALLBACK_FROM_EMAIL ); ?>]"
349
+ >
350
+ <br>
351
+ <small><?php esc_html_e( "Use allowed email, for example: If you are using Gmail, type your Gmail adress.", 'post-smtp' ); ?></small>
352
+ </td>
353
+ </tr>
354
+
355
+ <tr valign="">
356
+ <th scope="row"><?php esc_html_e( 'Use SMTP Authentication?', 'post-smtp' ); ?></th>
357
+ <td>
358
+ <label>
359
+ <input name="postman_options[<?php echo esc_attr( PostmanOptions::FALLBACK_SMTP_USE_AUTH ); ?>]"
360
+ type="radio" value="none"<?php checked( $this->options->getFallbackAuth(), 'none' ); ?>>
361
+ <?php esc_html_e( 'No', 'post-smtp' ); ?>
362
+ </label>
363
+ &nbsp;
364
+ <label>
365
+ <input name="postman_options[<?php echo esc_attr( PostmanOptions::FALLBACK_SMTP_USE_AUTH ); ?>]"
366
+ type="radio" value="login"<?php checked( $this->options->getFallbackAuth(), 'login' ); ?>>
367
+ <?php esc_html_e( 'Yes', 'post-smtp' ); ?>
368
+ </label>
369
+ </td>
370
+ </tr>
371
+
372
+ <tr>
373
+ <th scope="row"><?php esc_html_e('User name', 'post-smtp' ); ?></th>
374
+ <td>
375
+ <input type="text" id="fallback-smtp-username"
376
+ value="<?php echo esc_attr( $this->options->getFallbackUsername() ); ?>"
377
+ name="postman_options[<?php echo esc_attr( PostmanOptions::FALLBACK_SMTP_USERNAME ); ?>]"
378
+ >
379
+ </td>
380
+ </tr>
381
+
382
+ <tr>
383
+ <th scope="row"><?php esc_html_e('Password', 'post-smtp' ); ?></th>
384
+ <td>
385
+ <input type="password" id="fallback-smtp-password"
386
+ value="<?php echo esc_attr( PostmanUtils::obfuscatePassword( $this->options->getFallbackPassword() ) ); ?>"
387
+ name="postman_options[<?php echo esc_attr( PostmanOptions::FALLBACK_SMTP_PASSWORD ); ?>]"
388
+ >
389
+ </td>
390
+ </tr>
391
+
392
+ </table>
393
+ </section>
394
+ <!-- Fallback End -->
395
+
396
+ <?php
397
+ print '<section id="message_config">';
398
+ do_settings_sections( PostmanAdminController::MESSAGE_SENDER_OPTIONS );
399
+ do_settings_sections( PostmanAdminController::MESSAGE_FROM_OPTIONS );
400
+ do_settings_sections( PostmanAdminController::EMAIL_VALIDATION_OPTIONS );
401
+ do_settings_sections( PostmanAdminController::MESSAGE_OPTIONS );
402
+ do_settings_sections( PostmanAdminController::MESSAGE_HEADERS_OPTIONS );
403
+ print '</section>';
404
+ print '<section id="logging_config">';
405
+ do_settings_sections( PostmanAdminController::LOGGING_OPTIONS );
406
+ print '</section>';
407
+ /*
408
+ * print '<section id="logging_config">';
409
+ * do_settings_sections ( PostmanAdminController::MULTISITE_OPTIONS );
410
+ * print '</section>';
411
+ */
412
+ print '<section id="advanced_options_config">';
413
+ do_settings_sections( PostmanAdminController::NETWORK_OPTIONS );
414
+ do_settings_sections( PostmanAdminController::ADVANCED_OPTIONS );
415
+ print '</section>';
416
+
417
+ do_action( 'post_smtp_settings_menu' );
418
+
419
+ submit_button( 'Save Changes', 'ps-btn-orange' );
420
+ print '</form>';
421
+ print '</div>';
422
+ print '</div>';
423
+ }
424
+
425
+ /**
426
+ */
427
+ public function outputWizardContent() {
428
+ // Set default values for input fields
429
+ $this->options->setMessageSenderEmailIfEmpty( wp_get_current_user()->user_email );
430
+ $this->options->setMessageSenderNameIfEmpty( wp_get_current_user()->display_name );
431
+
432
+ // construct Wizard
433
+ print '<div class="wrap">';
434
+
435
+ PostmanViewController::outputChildPageHeader( __( 'Setup Wizard', 'post-smtp' ) );
436
+
437
+ print '<form id="postman_wizard" method="post" action="options.php">';
438
+
439
+ // account tab
440
+ // message tab
441
+ printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::PREVENT_MESSAGE_SENDER_EMAIL_OVERRIDE ), esc_attr( $this->options->isPluginSenderEmailEnforced() ) );
442
+ printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::PREVENT_MESSAGE_SENDER_NAME_OVERRIDE ), esc_attr( $this->options->isPluginSenderNameEnforced() ) );
443
+ printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::REPLY_TO ), esc_attr( $this->options->getReplyTo() ) );
444
+ printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::FORCED_TO_RECIPIENTS ), esc_attr( $this->options->getForcedToRecipients() ) );
445
+ printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::FORCED_CC_RECIPIENTS ), esc_attr( $this->options->getForcedCcRecipients() ) );
446
+ printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::FORCED_BCC_RECIPIENTS ), esc_attr( $this->options->getForcedBccRecipients() ) );
447
+ printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::ADDITIONAL_HEADERS ), esc_attr( $this->options->getAdditionalHeaders() ) );
448
+ printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::DISABLE_EMAIL_VALIDAITON ), esc_attr( $this->options->isEmailValidationDisabled() ) );
449
+
450
+ // logging tab
451
+ printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::MAIL_LOG_ENABLED_OPTION ), esc_attr( $this->options->getMailLoggingEnabled() ) );
452
+ printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::MAIL_LOG_MAX_ENTRIES ), esc_attr( $this->options->getMailLoggingMaxEntries() ) );
453
+ printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::TRANSCRIPT_SIZE ), esc_attr( $this->options->getTranscriptSize() ) );
454
+
455
+ // advanced tab
456
+ printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::CONNECTION_TIMEOUT ), esc_attr( $this->options->getConnectionTimeout() ) );
457
+ printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::READ_TIMEOUT ), esc_attr( $this->options->getReadTimeout() ) );
458
+ printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::LOG_LEVEL ), esc_attr( $this->options->getLogLevel() ) );
459
+ printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::RUN_MODE ), esc_attr( $this->options->getRunMode() ) );
460
+ printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::STEALTH_MODE ), esc_attr( $this->options->isStealthModeEnabled() ) );
461
+ printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::TEMPORARY_DIRECTORY ), esc_attr( $this->options->getTempDirectory() ) );
462
+
463
+ wp_nonce_field('post-smtp', 'security' );
464
+
465
+ // display the setting text
466
+ settings_fields( PostmanAdminController::SETTINGS_GROUP_NAME );
467
+
468
+ // Wizard Step 0
469
+ printf( '<h5>%s</h5>', esc_html_x( 'Import Configuration', 'Wizard Step Title', 'post-smtp' ) );
470
+ print '<fieldset>';
471
+ printf( '<legend>%s</legend>', esc_html_x( 'Import configuration from another plugin?', 'Wizard Step Title', 'post-smtp' ) );
472
+ printf( '<p>%s</p>', esc_html__( 'If you had a working configuration with another Plugin, the Setup Wizard can begin with those settings.', 'post-smtp' ) );
473
+
474
+ $style = '';
475
+
476
+ if( !$this->importableConfiguration->isImportAvailable() ) {
477
+
478
+ $style = 'style="display: none"';
479
+
480
+ printf(
481
+ '<div class="no-configuration ps-config-bar">
482
+ <div class="ps-right">
483
+ %s
484
+ </div>
485
+ <div class="clear"></div>
486
+ </div>',
487
+ esc_html__( 'No other SMTP plugin configuration has been detected in your installation. You can skip this step.', 'post-smtp' )
488
+ );
489
+
490
+ }
491
+
492
+ printf(
493
+ '<div class="input_auth_type">
494
+ <div class="ps-socket-wizad-row" %s>
495
+ <label>
496
+
497
+ <div class="ps-single-socket-outer">
498
+ <img src="%s" class="ps-wizard-socket-logo" width="165px">
499
+ </div>
500
+ <input type="radio" id="import_none" name="input_plugin" value="%s" checked="checked">
501
+ <label> %s</label>
502
+ </label>',
503
+ wp_kses_post( $style ),
504
+ esc_url( POST_SMTP_ASSETS . "images/logos/gear.png" ),
505
+ 'none',
506
+ esc_html__( 'None', 'post-smtp' )
507
+ );
508
+
509
+ $row = 1;
510
+
511
+ if ( $this->importableConfiguration->isImportAvailable() ) {
512
+ foreach ( $this->importableConfiguration->getAvailableOptions() as $options ) {
513
+ printf(
514
+ '<label>
515
+ <div class="ps-single-socket-outer">
516
+ <img src="%s" class="ps-wizard-socket-logo" width="165px">
517
+ </div>
518
+ <input type="radio" id="import_none" name="input_plugin" value="%s" checked="checked">
519
+ <label> %s</label>
520
+ </label>',
521
+ esc_url( $options->getPluginLogo() ),
522
+ esc_attr( $options->getPluginSlug() ),
523
+ esc_html( $options->getPluginName() )
524
+ );
525
+
526
+ $row++;
527
+
528
+ if( $row == 3 ) {
529
+ print '</div>';
530
+ print '<div class="ps-socket-wizad-row">';
531
+ $row = 0;
532
+ }
533
+ }
534
+ }
535
+
536
+ print '</div>';
537
+ print '</div>';
538
+ print '</fieldset>';
539
+
540
+ // Wizard Step 1
541
+ printf( '<h5>%s</h5>', esc_html_x( 'Sender Details', 'Wizard Step Title', 'post-smtp' ) );
542
+ print '<fieldset>';
543
+ printf( '<legend>%s</legend>', esc_html_x( 'Who is the mail coming from?', 'Wizard Step Title', 'post-smtp' ) );
544
+ printf( '<p>%s</p>', esc_html__( 'Enter the email address and name you\'d like to send mail as.', 'post-smtp' ) );
545
+ printf(
546
+ '<p>%s <em>%s</em> %s</p>',
547
+ esc_html__( 'Please note that to prevent abuse, many email services will ', 'post-smtp' ),
548
+ esc_html__( 'not', 'post-smtp' ),
549
+ esc_html__( 'let you send from an email address other than the one you authenticate with.', 'post-smtp' )
550
+ );
551
+
552
+ print( '<div class="ps-ib ps-w-50">' );
553
+ printf( '<label for="postman_options[sender_name]">%s</label>', esc_html__( 'Name', 'post-smtp' ) );
554
+ print wp_kses_post( $this->settingsRegistry->sender_name_callback() );
555
+ print( '</div>' );
556
+
557
+ print( '<div class="ps-ib ps-w-50">' );
558
+ printf( '<label for="postman_options[sender_email]">%s</label>', esc_html__( 'Email Address', 'post-smtp' ) );
559
+ print wp_kses_post( $this->settingsRegistry->from_email_callback() );
560
+ print( '</div>' );
561
+
562
+ print( '<div class="clear"></div>' );
563
+
564
+ print '</fieldset>';
565
+
566
+ // Wizard Step 2
567
+ printf( '<h5>%s</h5>', esc_html__( 'Outgoing Mail Server Hostname', 'post-smtp' ) );
568
+ print '<fieldset>';
569
+ foreach ( PostmanTransportRegistry::getInstance()->getTransports() as $transport ) {
570
+ $transport->printWizardMailServerHostnameStep();
571
+ }
572
+ print '</fieldset>';
573
+
574
+ // Wizard Step 3
575
+ printf( '<h5>%s</h5>', esc_html__( 'Connectivity Test', 'post-smtp' ) );
576
+ print '<fieldset>';
577
+ printf( '<legend>%s</legend>', esc_html__( 'How will the connection to the mail server be established?', 'post-smtp' ) );
578
+ printf( '<p>%s</p>', esc_html__( 'Your connection settings depend on what your email service provider offers, and what your WordPress host allows.', 'post-smtp' ) );
579
+ printf( '<p id="connectivity_test_status">%s: <span id="port_test_status">%s</span></p>', esc_html__( 'Connectivity Test', 'post-smtp' ), esc_html_x( 'Ready', 'TCP Port Test Status', 'post-smtp' ) );
580
+ printf( '<p class="ajax-loader" style="display:none"><img src="%s"/></p>', esc_url( plugins_url( 'post-smtp/style/ajax-loader.gif' ) ) );
581
+ printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]">', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::TRANSPORT_TYPE ) );
582
+ printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]">', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::PORT ) );
583
+ printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]">', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::SECURITY_TYPE ) );
584
+ printf( '<input type="hidden" id="input_%2$s" name="%1$s[%2$s]">', esc_attr( PostmanOptions::POSTMAN_OPTIONS ), esc_attr( PostmanOptions::AUTHENTICATION_TYPE ) );
585
+ print '<legend id="wizard_recommendation"></legend>';
586
+ /* Translators: Where %1$s is the socket identifier and %2$s is the authentication type */
587
+ printf( '<p class="user_override" style="display:none"><label><span>%s:</span></label> <div id="user_socket_override" class="user_override"></div></p>', esc_html_x( 'Socket', 'A socket is the network term for host and port together', 'post-smtp' ) );
588
+ printf( '<p class="user_override" style="display:none"><label><span>%s:</span></label> <div id="user_auth_override" class="user_override"></div></p>', esc_html__( 'Authentication', 'post-smtp' ) );
589
+ print ('<p><span id="smtp_mitm" style="display:none; background-color:yellow"></span></p>') ;
590
+ $warning = esc_html__( 'Warning', 'post-smtp' );
591
+ $clearCredentialsWarning = esc_html__( 'This configuration option will send your authorization credentials in the clear.', 'post-smtp' );
592
+ printf(
593
+ '<p id="smtp_not_secure" style="display:none"><span style="background-color:yellow">%s: %s</span></p>',
594
+ esc_html( $warning ),
595
+ esc_html( $clearCredentialsWarning )
596
+ );
597
+ print '</fieldset>';
598
+
599
+ // Wizard Step 4
600
+ printf( '<h5>%s</h5>', esc_html__( 'Authentication', 'post-smtp' ) );
601
+ print '<fieldset>';
602
+ printf( '<legend>%s</legend>', esc_html__( 'How will you prove your identity to the mail server?', 'post-smtp' ) );
603
+ foreach ( PostmanTransportRegistry::getInstance()->getTransports() as $transport ) {
604
+ $transport->printWizardAuthenticationStep();
605
+ }
606
+ print '</fieldset>';
607
+
608
+ // Wizard Step 5 - Notificiations
609
+ printf( '<h5>%s</h5>', esc_html__( 'Notifications', 'post-smtp' ) );
610
+ print '<fieldset>';
611
+ printf( '<legend>%s</legend>', esc_html__( 'Select a notify service to notify you when an email is failed to delivered.', 'post-smtp' ) );
612
+
613
+ ?>
614
+ <select id="input_notification_service" class="input_notification_service" name="postman_options[notification_service]">
615
+ <option value="default">Email</option>
616
+ <option value="pushover">Pushover</option>
617
+ <option value="slack">Slack</option>
618
+ </select>
619
+ <div id="pushover_cred" style="display: none;">
620
+ <h2><?php esc_html_e( 'Pushover Credentials', 'post-smtp' ); ?></h2>
621
+ <table class="form-table">
622
+ <tbody>
623
+ <tr>
624
+ <th scope="row"><?php esc_html_e( 'Pushover User Key', 'post-smtp' ); ?></th>
625
+ <td>
626
+ <input type="password" id="pushover_user" name="postman_options[pushover_user]" value="">
627
+ </td>
628
+ </tr>
629
+ <tr>
630
+ <th scope="row"><?php esc_html_e( 'Pushover App Token', 'post-smtp' ); ?></th>
631
+ <td>
632
+ <input type="password" id="pushover_token" name="postman_options[pushover_token]" value="">
633
+ </td>
634
+ </tr>
635
+ </tbody>
636
+ </table>
637
+ </div>
638
+ <div id="slack_cred" style="display: none;">
639
+ <h2><?php esc_html_e( 'Slack Credentials', 'post-smtp' ); ?></h2>
640
+ <table class="form-table">
641
+ <tbody>
642
+ <tr>
643
+ <th scope="row"><?php esc_html_e( 'Slack webhook', 'post-smtp' ); ?></th>
644
+ <td>
645
+ <input type="password" id="slack_token" name="postman_options[slack_token]" value="">
646
+ <a target="_blank" class="" href="https://slack.postmansmtp.com/">
647
+ <?php esc_html_e( 'Get your webhook URL here.', 'post-smtp' ); ?>
648
+ </a>
649
+ </td>
650
+ </tr>
651
+ </tbody>
652
+ </table>
653
+ </div>
654
+
655
+ <div id="use-chrome-extension">
656
+ <h2><?php esc_html_e( 'Push To Chrome Extension', 'post-smtp' ); ?></h2>
657
+ <table class="form-table">
658
+ <tbody>
659
+ <tr>
660
+ <th scope="row"><?php esc_html_e( 'This is an extra notification to the selection above', 'post-smtp' ); ?></th>
661
+ <td>
662
+ <input type="checkbox" id="notification_use_chrome" name="postman_options[notification_use_chrome]">
663
+ <a target="_blank" class="" href="https://chrome.google.com/webstore/detail/npklmbkpbknkmbohdbpikeidiaekjoch">
664
+ <?php esc_html_e( 'You can download the chrome extension here (if link not available, check later).', 'post-smtp' ); ?>
665
+ </a>
666
+ </td>
667
+ </tr>
668
+ <tr>
669
+ <th scope="row"><?php esc_html_e( 'Your UID as you see in the extension.', 'post-smtp' ); ?></th>
670
+ <td>
671
+ <input type="password" id="notification_chrome_uid" name="postman_options[notification_chrome_uid]" value="">
672
+ </td>
673
+ </tr>
674
+ </tbody>
675
+ </table>
676
+ </div>
677
+
678
+ <?php
679
+ print '</fieldset>';
680
+
681
+ // Wizard Step 6
682
+ printf( '<h5>%s</h5>', esc_html_x( 'Finish', 'The final step of the Wizard', 'post-smtp' ) );
683
+ print '<fieldset>';
684
+ printf( '<legend>%s</legend>', esc_html_x( 'You\'re Done!', 'Wizard Step Title', 'post-smtp' ) );
685
+ print '<section>';
686
+ printf( '<p>%s</p>', esc_html__( 'Click Finish to save these settings, then:', 'post-smtp' ) );
687
+ print '<ul style="margin-left: 20px">';
688
+ printf( '<li class="wizard-auth-oauth2">%s</li>', esc_html__( 'Grant permission with the Email Provider for Postman to send email and', 'post-smtp' ) );
689
+ printf( '<li>%s</li>', esc_html__( 'Send yourself a Test Email to make sure everything is working!', 'post-smtp' ) );
690
+ print '</ul>';
691
+
692
+ // Get PHPmailer recommendation
693
+ Postman::getMailerTypeRecommend();
694
+
695
+ $in_wizard = true;
696
+
697
+ print '</section>';
698
+ print '</fieldset>';
699
+ print '</form>';
700
+ print '</div>';
701
+ }
702
+ }
703
+
704
+ /**
705
+ *
706
+ * @author jasonhendriks
707
+ */
708
+ class PostmanGetHostnameByEmailAjaxController extends PostmanAbstractAjaxHandler {
709
+ const IS_GOOGLE_PARAMETER = 'is_google';
710
+ function __construct() {
711
+ parent::__construct();
712
+ PostmanUtils::registerAjaxHandler( 'postman_check_email', $this, 'getAjaxHostnameByEmail' );
713
+ }
714
+ /**
715
+ * This Ajax function retrieves the smtp hostname for a give e-mail address
716
+ */
717
+ function getAjaxHostnameByEmail() {
718
+
719
+ check_admin_referer('post-smtp', 'security');
720
+
721
+ if( !current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_NAME ) ) {
722
+ wp_send_json_error(
723
+ array(
724
+ 'Message' => 'Unauthorized.'
725
+ ),
726
+ 401
727
+ );
728
+ }
729
+
730
+ $goDaddyHostDetected = $this->getBooleanRequestParameter( 'go_daddy' );
731
+ $email = $this->getRequestParameter( 'email' );
732
+ $d = new PostmanSmtpDiscovery( $email );
733
+ $smtp = $d->getSmtpServer();
734
+ $this->logger->debug( 'given email ' . $email . ', smtp server is ' . $smtp );
735
+ $this->logger->trace( $d );
736
+ if ( $goDaddyHostDetected && ! $d->isGoogle ) {
737
+ // override with the GoDaddy SMTP server
738
+ $smtp = 'relay-hosting.secureserver.net';
739
+ $this->logger->debug( 'detected GoDaddy SMTP server, smtp server is ' . $smtp );
740
+ }
741
+ $response = array(
742
+ 'hostname' => $smtp,
743
+ self::IS_GOOGLE_PARAMETER => $d->isGoogle,
744
+ 'is_go_daddy' => $d->isGoDaddy,
745
+ 'is_well_known' => $d->isWellKnownDomain,
746
+ );
747
+ $this->logger->trace( $response );
748
+ wp_send_json_success( $response );
749
+ }
750
+ }
751
+ class PostmanManageConfigurationAjaxHandler extends PostmanAbstractAjaxHandler {
752
+ function __construct() {
753
+ parent::__construct();
754
+ PostmanUtils::registerAjaxHandler( 'manual_config', $this, 'getManualConfigurationViaAjax' );
755
+ PostmanUtils::registerAjaxHandler( 'get_wizard_configuration_options', $this, 'getWizardConfigurationViaAjax' );
756
+ }
757
+
758
+ /**
759
+ * Handle a Advanced Configuration request with Ajax
760
+ *
761
+ * @throws Exception
762
+ */
763
+ function getManualConfigurationViaAjax() {
764
+
765
+ check_admin_referer('post-smtp', 'security');
766
+
767
+ if( !current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_NAME ) ) {
768
+ wp_send_json_error(
769
+ array(
770
+ 'Message' => 'Unauthorized.'
771
+ ),
772
+ 401
773
+ );
774
+ }
775
+
776
+ $queryTransportType = $this->getTransportTypeFromRequest();
777
+ $queryAuthType = $this->getAuthenticationTypeFromRequest();
778
+ $queryHostname = $this->getHostnameFromRequest();
779
+
780
+ // the outgoing server hostname is only required for the SMTP Transport
781
+ // the Gmail API transport doesn't use an SMTP server
782
+ $transport = PostmanTransportRegistry::getInstance()->getTransport( $queryTransportType );
783
+ if ( ! $transport ) {
784
+ throw new Exception( 'Unable to find transport ' . $queryTransportType );
785
+ }
786
+
787
+ // create the response
788
+ $response = $transport->populateConfiguration( $queryHostname );
789
+ $response ['referer'] = 'manual_config';
790
+
791
+ // set the display_auth to oauth2 if the transport needs it
792
+ if ( $transport->isOAuthUsed( $queryAuthType ) ) {
793
+ $response ['display_auth'] = 'oauth2';
794
+ $this->logger->debug( 'ajaxRedirectUrl answer display_auth:' . $response ['display_auth'] );
795
+ }
796
+ $this->logger->trace( $response );
797
+ wp_send_json_success( $response );
798
+ }
799
+
800
+ /**
801
+ * Once the Port Tests have run, the results are analyzed.
802
+ * The Transport place bids on the sockets and highest bid becomes the recommended
803
+ * The UI response is built so the user may choose a different socket with different options.
804
+ */
805
+ function getWizardConfigurationViaAjax() {
806
+
807
+ check_admin_referer('post-smtp', 'security');
808
+
809
+ if( !current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_NAME ) ) {
810
+ wp_send_json_error(
811
+ array(
812
+ 'Message' => 'Unauthorized.'
813
+ ),
814
+ 401
815
+ );
816
+ }
817
+
818
+ $this->logger->debug( 'in getWizardConfiguration' );
819
+ $originalSmtpServer = $this->getRequestParameter( 'original_smtp_server' );
820
+ $queryHostData = $this->getHostDataFromRequest();
821
+ $sockets = array();
822
+ foreach ( $queryHostData as $id => $datum ) {
823
+ array_push( $sockets, new PostmanWizardSocket( $datum ) );
824
+ }
825
+
826
+ $this->logger->error( $sockets );
827
+ $userPortOverride = $this->getUserPortOverride();
828
+ $userAuthOverride = $this->getUserAuthOverride();
829
+
830
+ // determine a configuration recommendation
831
+ $winningRecommendation = $this->getWinningRecommendation( $sockets, $userPortOverride, $userAuthOverride, $originalSmtpServer );
832
+ if ( $this->logger->isTrace() ) {
833
+ $this->logger->trace( 'winning recommendation:' );
834
+ $this->logger->trace( $winningRecommendation );
835
+ }
836
+
837
+ // create the reponse
838
+ $response = array();
839
+ $configuration = array();
840
+ $response ['referer'] = 'wizard';
841
+ if ( isset( $userPortOverride ) || isset( $userAuthOverride ) ) {
842
+ $configuration ['user_override'] = true;
843
+ }
844
+
845
+ if ( isset( $winningRecommendation ) ) {
846
+
847
+ // create an appropriate (theoretical) transport
848
+ $transport = PostmanTransportRegistry::getInstance()->getTransport( $winningRecommendation ['transport'] );
849
+
850
+ // create user override menu
851
+ $overrideMenu = $this->createOverrideMenus( $sockets, $winningRecommendation, $userPortOverride, $userAuthOverride );
852
+ if ( $this->logger->isTrace() ) {
853
+ $this->logger->trace( 'override menu:' );
854
+ $this->logger->trace( $overrideMenu );
855
+ }
856
+
857
+ $queryHostName = $winningRecommendation ['hostname'];
858
+ if ( $this->logger->isDebug() ) {
859
+ $this->logger->debug( 'Getting scribe for ' . $queryHostName );
860
+ }
861
+ $generalConfig1 = $transport->populateConfiguration( $queryHostName );
862
+ $generalConfig2 = $transport->populateConfigurationFromRecommendation( $winningRecommendation );
863
+ $configuration = array_merge( $configuration, $generalConfig1, $generalConfig2 );
864
+ $response ['override_menu'] = $overrideMenu;
865
+ $response ['configuration'] = $configuration;
866
+ if ( $this->logger->isTrace() ) {
867
+ $this->logger->trace( 'configuration:' );
868
+ $this->logger->trace( $configuration );
869
+ $this->logger->trace( 'response:' );
870
+ $this->logger->trace( $response );
871
+ }
872
+ wp_send_json_success( $response );
873
+ } else {
874
+ /* translators: where %s is the URL to the Connectivity Test page */
875
+ $configuration ['message'] = sprintf( __( 'Postman can\'t find any way to send mail on your system. Run a <a href="%s">connectivity test</a>.', 'post-smtp' ), PostmanViewController::getPageUrl( PostmanConnectivityTestController::PORT_TEST_SLUG ) );
876
+ $response ['configuration'] = $configuration;
877
+ if ( $this->logger->isTrace() ) {
878
+ $this->logger->trace( 'configuration:' );
879
+ $this->logger->trace( $configuration );
880
+ }
881
+ wp_send_json_error( $response );
882
+ }
883
+ }
884
+
885
+ /**
886
+ * // for each successful host/port combination
887
+ * // ask a transport if they support it, and if they do at what priority is it
888
+ * // configure for the highest priority you find
889
+ *
890
+ * @param mixed $queryHostData
891
+ * @return mixed
892
+ */
893
+ private function getWinningRecommendation( $sockets, $userSocketOverride, $userAuthOverride, $originalSmtpServer ) {
894
+
895
+ foreach ( $sockets as $socket ) {
896
+ $winningRecommendation = $this->getWin( $socket, $userSocketOverride, $userAuthOverride, $originalSmtpServer );
897
+ $this->logger->error( $socket->label );
898
+ }
899
+
900
+ return $winningRecommendation;
901
+ }
902
+
903
+ /**
904
+ *
905
+ * @param PostmanWizardSocket $socket
906
+ * @param mixed $userSocketOverride
907
+ * @param mixed $userAuthOverride
908
+ * @param mixed $originalSmtpServer
909
+ * @return mixed
910
+ */
911
+ private function getWin( PostmanWizardSocket $socket, $userSocketOverride, $userAuthOverride, $originalSmtpServer ) {
912
+ static $recommendationPriority = - 1;
913
+ static $winningRecommendation = null;
914
+ $available = $socket->success;
915
+ if ( $available ) {
916
+ $this->logger->debug( sprintf( 'Asking for judgement on %s:%s', $socket->hostname, $socket->port ) );
917
+ $recommendation = PostmanTransportRegistry::getInstance()->getRecommendation( $socket, $userAuthOverride, $originalSmtpServer );
918
+ $recommendationId = sprintf( '%s_%s', $socket->hostname, $socket->port );
919
+ $recommendation ['id'] = $recommendationId;
920
+ $this->logger->debug( sprintf( 'Got a recommendation: [%d] %s', $recommendation ['priority'], $recommendationId ) );
921
+ if ( isset( $userSocketOverride ) ) {
922
+ if ( $recommendationId == $userSocketOverride ) {
923
+ $winningRecommendation = $recommendation;
924
+ $this->logger->debug( sprintf( 'User chosen socket %s is the winner', $recommendationId ) );
925
+ }
926
+ } elseif ( $recommendation && $recommendation ['priority'] > $recommendationPriority ) {
927
+ $recommendationPriority = $recommendation ['priority'];
928
+ $winningRecommendation = $recommendation;
929
+ }
930
+ $socket->label = $recommendation ['label'];
931
+ }
932
+
933
+ return $winningRecommendation;
934
+ }
935
+
936
+ /**
937
+ *
938
+ * @param mixed $queryHostData
939
+ * @return multitype:
940
+ */
941
+ private function createOverrideMenus( $sockets, $winningRecommendation, $userSocketOverride, $userAuthOverride ) {
942
+
943
+ $overrideMenu = array();
944
+ $last_items = array();
945
+
946
+ foreach ( $sockets as $socket ) {
947
+
948
+ $overrideItem = $this->createOverrideMenu( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
949
+ if ( $overrideItem != null ) {
950
+
951
+ $transport = PostmanTransportRegistry::getInstance()->getTransport( $socket->transport );
952
+
953
+ //If class has constant
954
+ if( defined( get_class( $transport ) . "::PRIORITY" ) ) {
955
+
956
+ $priority = $transport::PRIORITY;
957
+ $overrideMenu[$priority] = $overrideItem;
958
+
959
+ }
960
+ else {
961
+
962
+ $last_items[] = $overrideItem;
963
+
964
+ }
965
+
966
+ }
967
+
968
+ }
969
+
970
+ //Sort in DESC order
971
+ krsort( $overrideMenu );
972
+
973
+ //Start Placing sockets in last, because they don't have there own priority.
974
+ foreach( $last_items as $item ) {
975
+
976
+ $overrideMenu[] = $item;
977
+
978
+ }
979
+
980
+ $menu = array();
981
+ foreach ( $overrideMenu as $key ) {
982
+ array_push( $menu, $key );
983
+ }
984
+
985
+ return $menu;
986
+
987
+ }
988
+
989
+ /**
990
+ *
991
+ * @param PostmanWizardSocket $socket
992
+ * @param mixed $winningRecommendation
993
+ * @param mixed $userSocketOverride
994
+ * @param mixed $userAuthOverride
995
+ */
996
+ private function createOverrideMenu( PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride ) {
997
+ if ( $socket->success ) {
998
+ $transport = PostmanTransportRegistry::getInstance()->getTransport( $socket->transport );
999
+ $this->logger->debug( sprintf( 'Transport %s is building the override menu for socket', $transport->getSlug() ) );
1000
+ $overrideItem = $transport->createOverrideMenu( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
1001
+ return $overrideItem;
1002
+ }
1003
+ return null;
1004
+ }
1005
+
1006
+ /**
1007
+ */
1008
+ private function getTransportTypeFromRequest() {
1009
+ return $this->getRequestParameter( 'transport' );
1010
+ }
1011
+
1012
+ /**
1013
+ */
1014
+ private function getHostnameFromRequest() {
1015
+ return $this->getRequestParameter( 'hostname' );
1016
+ }
1017
+
1018
+ /**
1019
+ */
1020
+ private function getAuthenticationTypeFromRequest() {
1021
+ return $this->getRequestParameter( 'auth_type' );
1022
+ }
1023
+
1024
+ /**
1025
+ */
1026
+ private function getHostDataFromRequest() {
1027
+ return $this->getRequestParameter( 'host_data' );
1028
+ }
1029
+
1030
+ /**
1031
+ */
1032
+ private function getUserPortOverride() {
1033
+ return $this->getRequestParameter( 'user_port_override' );
1034
+ }
1035
+
1036
+ /**
1037
+ */
1038
+ private function getUserAuthOverride() {
1039
+ return $this->getRequestParameter( 'user_auth_override' );
1040
+ }
1041
+ }
1042
+ class PostmanImportConfigurationAjaxController extends PostmanAbstractAjaxHandler {
1043
+ private $options;
1044
+ /**
1045
+ * Constructor
1046
+ *
1047
+ * @param PostmanOptions $options
1048
+ */
1049
+ function __construct( PostmanOptions $options ) {
1050
+ parent::__construct();
1051
+ $this->options = $options;
1052
+ PostmanUtils::registerAjaxHandler( 'import_configuration', $this, 'getConfigurationFromExternalPluginViaAjax' );
1053
+ }
1054
+
1055
+ /**
1056
+ * This function extracts configuration details form a competing SMTP plugin
1057
+ * and pushes them into the Postman configuration screen.
1058
+ */
1059
+ function getConfigurationFromExternalPluginViaAjax() {
1060
+
1061
+ check_admin_referer('post-smtp', 'security');
1062
+
1063
+ if( !current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_NAME ) ) {
1064
+ wp_send_json_error(
1065
+ array(
1066
+ 'Message' => 'Unauthorized.'
1067
+ ),
1068
+ 401
1069
+ );
1070
+ }
1071
+
1072
+ $importableConfiguration = new PostmanImportableConfiguration();
1073
+ $plugin = $this->getRequestParameter( 'plugin' );
1074
+ $this->logger->debug( 'Looking for config=' . $plugin );
1075
+ foreach ( $importableConfiguration->getAvailableOptions() as $this->options ) {
1076
+ if ( $this->options->getPluginSlug() == $plugin ) {
1077
+ $this->logger->debug( 'Sending configuration response' );
1078
+ $response = array(
1079
+ PostmanOptions::MESSAGE_SENDER_EMAIL => $this->options->getMessageSenderEmail(),
1080
+ PostmanOptions::MESSAGE_SENDER_NAME => $this->options->getMessageSenderName(),
1081
+ PostmanOptions::HOSTNAME => $this->options->getHostname(),
1082
+ PostmanOptions::PORT => $this->options->getPort(),
1083
+ PostmanOptions::AUTHENTICATION_TYPE => $this->options->getAuthenticationType(),
1084
+ PostmanOptions::SECURITY_TYPE => $this->options->getEncryptionType(),
1085
+ PostmanOptions::BASIC_AUTH_USERNAME => $this->options->getUsername(),
1086
+ PostmanOptions::BASIC_AUTH_PASSWORD => $this->options->getPassword(),
1087
+ 'success' => true,
1088
+ );
1089
+ break;
1090
+ }
1091
+ }
1092
+ if ( ! isset( $response ) ) {
1093
+ $response = array(
1094
+ 'success' => false,
1095
+ );
1096
+ }
1097
+ wp_send_json( $response );
1098
+ }
1099
+ }
Postman/Postman-Configuration/PostmanImportableConfiguration.php CHANGED
@@ -1,686 +1,692 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- if (! interface_exists ( 'PostmanPluginOptions' )) {
7
- interface PostmanPluginOptions {
8
- public function getPluginSlug();
9
- public function getPluginName();
10
- public function isImportable();
11
- public function getHostname();
12
- public function getPort();
13
- public function getMessageSenderEmail();
14
- public function getMessageSenderName();
15
- public function getAuthenticationType();
16
- public function getEncryptionType();
17
- public function getUsername();
18
- public function getPassword();
19
- /**
20
- * Get plugin's logo
21
- *
22
- * @since 2.1
23
- * @version 1.0
24
- */
25
- public function getPluginLogo();
26
- }
27
- }
28
- if (! class_exists ( 'PostmanImportableConfiguration' )) {
29
-
30
- /**
31
- * This class instantiates the Connectors for new users to Postman.
32
- * It determines which Connectors can supply configuration data
33
- *
34
- * @author jasonhendriks
35
- *
36
- */
37
- class PostmanImportableConfiguration {
38
- private $lazyInit;
39
- private $availableOptions;
40
- private $importAvailable;
41
- private $logger;
42
- function __construct() {
43
- $this->logger = new PostmanLogger ( get_class ( $this ) );
44
- }
45
- function init() {
46
- if (! $this->lazyInit) {
47
- $this->queueIfAvailable ( new PostmanEasyWpSmtpOptions () );
48
- $this->queueIfAvailable ( new PostmanWpSmtpOptions () );
49
- $this->queueIfAvailable ( new PostmanWpMailBankOptions () );
50
- $this->queueIfAvailable ( new PostmanWpMailSmtpOptions () );
51
- $this->queueIfAvailable ( new PostmanCimySwiftSmtpOptions () );
52
- $this->queueIfAvailable ( new PostmanConfigureSmtpOptions () );
53
- }
54
- $this->lazyInit = true;
55
- }
56
- private function queueIfAvailable(PostmanPluginOptions $options) {
57
- $slug = $options->getPluginSlug ();
58
- if ($options->isImportable ()) {
59
- $this->availableOptions [$slug] = $options;
60
- $this->importAvailable = true;
61
- $this->logger->debug ( $slug . ' is importable' );
62
- } else {
63
- $this->logger->debug ( $slug . ' is not importable' );
64
- }
65
- }
66
- public function getAvailableOptions() {
67
- $this->init ();
68
- return $this->availableOptions;
69
- }
70
- public function isImportAvailable() {
71
- $this->init ();
72
- return $this->importAvailable;
73
- }
74
- }
75
- }
76
-
77
- if (! class_exists ( 'PostmanAbstractPluginOptions' )) {
78
-
79
- /**
80
- *
81
- * @author jasonhendriks
82
- */
83
- abstract class PostmanAbstractPluginOptions implements PostmanPluginOptions {
84
- protected $options;
85
- protected $logger;
86
- public function __construct() {
87
- $this->logger = new PostmanLogger ( get_class ( $this ) );
88
- }
89
- public function isValid() {
90
- $valid = true;
91
- $host = $this->getHostname ();
92
- $port = $this->getPort ();
93
- $fromEmail = $this->getMessageSenderEmail ();
94
- $fromName = $this->getMessageSenderName ();
95
- $auth = $this->getAuthenticationType ();
96
- $enc = $this->getEncryptionType ();
97
- $username = $this->getUsername ();
98
- $password = $this->getPassword ();
99
- $valid &= ! empty ( $host );
100
- $this->logger->trace ( 'host ok ' . $valid );
101
- $valid &= ! empty ( $port ) && absint ( $port ) > 0 && absint ( $port ) <= 65535;
102
- $this->logger->trace ( 'port ok ' . $valid );
103
- $valid &= ! empty ( $fromEmail );
104
- $this->logger->trace ( 'from email ok ' . $valid );
105
- $valid &= ! empty ( $fromName );
106
- $this->logger->trace ( 'from name ok ' . $valid );
107
- $valid &= ! empty ( $auth );
108
- $this->logger->trace ( 'auth ok ' . $valid );
109
- $valid &= ! empty ( $enc );
110
- $this->logger->trace ( 'enc ok ' . $valid );
111
- if ($auth != PostmanOptions::AUTHENTICATION_TYPE_NONE) {
112
- $valid &= ! empty ( $username );
113
- $valid &= ! empty ( $password );
114
- }
115
- $this->logger->trace ( 'user/pass ok ' . $valid );
116
- return $valid;
117
- }
118
- public function isImportable() {
119
- return $this->isValid ();
120
- }
121
- }
122
- }
123
-
124
- if (! class_exists ( 'PostmanConfigureSmtpOptions' )) {
125
- // ConfigureSmtp (aka "SMTP") - 80,000
126
- class PostmanConfigureSmtpOptions extends PostmanAbstractPluginOptions {
127
- const SLUG = 'configure_smtp';
128
- const PLUGIN_NAME = 'Configure SMTP';
129
- const MESSAGE_SENDER_EMAIL = 'from_email';
130
- const MESSAGE_SENDER_NAME = 'from_name';
131
- const HOSTNAME = 'host';
132
- const PORT = 'port';
133
- const AUTHENTICATION_TYPE = 'smtp_auth';
134
- const ENCRYPTION_TYPE = 'smtp_secure';
135
- const USERNAME = 'smtp_user';
136
- const PASSWORD = 'smtp_pass';
137
- public function __construct() {
138
- parent::__construct ();
139
- $this->options = get_option ( 'c2c_configure_smtp' );
140
- }
141
- public function getPluginSlug() {
142
- return self::SLUG;
143
- }
144
- public function getPluginName() {
145
- return self::PLUGIN_NAME;
146
- }
147
- public function getMessageSenderEmail() {
148
- if (isset ( $this->options [self::MESSAGE_SENDER_EMAIL] ))
149
- return $this->options [self::MESSAGE_SENDER_EMAIL];
150
- }
151
- public function getMessageSenderName() {
152
- if (isset ( $this->options [self::MESSAGE_SENDER_NAME] ))
153
- return $this->options [self::MESSAGE_SENDER_NAME];
154
- }
155
- public function getHostname() {
156
- if (isset ( $this->options [self::HOSTNAME] ))
157
- return $this->options [self::HOSTNAME];
158
- }
159
- public function getPort() {
160
- if (isset ( $this->options [self::PORT] ))
161
- return $this->options [self::PORT];
162
- }
163
- public function getUsername() {
164
- if (isset ( $this->options [self::USERNAME] ))
165
- return $this->options [self::USERNAME];
166
- }
167
- public function getPassword() {
168
- if (isset ( $this->options [self::PASSWORD] ))
169
- return $this->options [self::PASSWORD];
170
- }
171
- public function getAuthenticationType() {
172
- if (isset ( $this->options [self::AUTHENTICATION_TYPE] )) {
173
- if ($this->options [self::AUTHENTICATION_TYPE] == 1) {
174
- return PostmanOptions::AUTHENTICATION_TYPE_PLAIN;
175
- } else {
176
- return PostmanOptions::AUTHENTICATION_TYPE_NONE;
177
- }
178
- }
179
- }
180
- public function getEncryptionType() {
181
- if (isset ( $this->options [self::ENCRYPTION_TYPE] )) {
182
- switch ($this->options [self::ENCRYPTION_TYPE]) {
183
- case 'ssl' :
184
- return PostmanOptions::SECURITY_TYPE_SMTPS;
185
- case 'tls' :
186
- return PostmanOptions::SECURITY_TYPE_STARTTLS;
187
- case '' :
188
- return PostmanOptions::SECURITY_TYPE_NONE;
189
- }
190
- }
191
- }
192
-
193
- /**
194
- * Get plugin's logo
195
- *
196
- * @since 2.1
197
- * @version 1.0
198
- */
199
- public function getPluginLogo() {
200
- return POST_SMTP_ASSETS . "images/logos/configure-smtp.png";
201
- }
202
- }
203
- }
204
-
205
- if (! class_exists ( 'PostmanCimySwiftSmtpOptions' )) {
206
- // Cimy Swift - 9,000
207
- class PostmanCimySwiftSmtpOptions extends PostmanAbstractPluginOptions {
208
- const SLUG = 'cimy_swift_smtp';
209
- const PLUGIN_NAME = 'Cimy Swift SMTP';
210
- const MESSAGE_SENDER_EMAIL = 'sender_mail';
211
- const MESSAGE_SENDER_NAME = 'sender_name';
212
- const HOSTNAME = 'server';
213
- const PORT = 'port';
214
- const ENCRYPTION_TYPE = 'ssl';
215
- const USERNAME = 'username';
216
- const PASSWORD = 'password';
217
- public function __construct() {
218
- parent::__construct ();
219
- $this->options = get_option ( 'cimy_swift_smtp_options' );
220
- }
221
- public function getPluginSlug() {
222
- return self::SLUG;
223
- }
224
- public function getPluginName() {
225
- return self::PLUGIN_NAME;
226
- }
227
- public function getMessageSenderEmail() {
228
- if (isset ( $this->options [self::MESSAGE_SENDER_EMAIL] ))
229
- return $this->options [self::MESSAGE_SENDER_EMAIL];
230
- }
231
- public function getMessageSenderName() {
232
- if (isset ( $this->options [self::MESSAGE_SENDER_NAME] ))
233
- return $this->options [self::MESSAGE_SENDER_NAME];
234
- }
235
- public function getHostname() {
236
- if (isset ( $this->options [self::HOSTNAME] ))
237
- return $this->options [self::HOSTNAME];
238
- }
239
- public function getPort() {
240
- if (isset ( $this->options [self::PORT] ))
241
- return $this->options [self::PORT];
242
- }
243
- public function getUsername() {
244
- if (isset ( $this->options [self::USERNAME] ))
245
- return $this->options [self::USERNAME];
246
- }
247
- public function getPassword() {
248
- if (isset ( $this->options [self::PASSWORD] ))
249
- return $this->options [self::PASSWORD];
250
- }
251
- public function getAuthenticationType() {
252
- if (! empty ( $this->options [self::USERNAME] ) && ! empty ( $this->options [self::PASSWORD] )) {
253
- return PostmanOptions::AUTHENTICATION_TYPE_PLAIN;
254
- } else {
255
- return PostmanOptions::AUTHENTICATION_TYPE_NONE;
256
- }
257
- }
258
- public function getEncryptionType() {
259
- if (isset ( $this->options [self::ENCRYPTION_TYPE] )) {
260
- switch ($this->options [self::ENCRYPTION_TYPE]) {
261
- case 'ssl' :
262
- return PostmanOptions::SECURITY_TYPE_SMTPS;
263
- case 'tls' :
264
- return PostmanOptions::SECURITY_TYPE_STARTTLS;
265
- case '' :
266
- return PostmanOptions::SECURITY_TYPE_NONE;
267
- }
268
- }
269
- }
270
-
271
- /**
272
- * Get plugin's logo
273
- *
274
- * @since 2.1
275
- * @version 1.0
276
- */
277
- public function getPluginLogo() {
278
- return POST_SMTP_ASSETS . "images/logos/php.png";
279
- }
280
- }
281
- }
282
-
283
- // Easy WP SMTP - 40,000
284
- if (! class_exists ( 'PostmanEasyWpSmtpOptions' )) {
285
-
286
- /**
287
- * Imports Easy WP SMTP options into Postman
288
- *
289
- * @author jasonhendriks
290
- */
291
- class PostmanEasyWpSmtpOptions extends PostmanAbstractPluginOptions implements PostmanPluginOptions {
292
- const SLUG = 'easy_wp_smtp';
293
- const PLUGIN_NAME = 'Easy WP SMTP';
294
- const SMTP_SETTINGS = 'smtp_settings';
295
- const MESSAGE_SENDER_EMAIL = 'from_email_field';
296
- const MESSAGE_SENDER_NAME = 'from_name_field';
297
- const HOSTNAME = 'host';
298
- const PORT = 'port';
299
- const ENCRYPTION_TYPE = 'type_encryption';
300
- const AUTHENTICATION_TYPE = 'autentication';
301
- const USERNAME = 'username';
302
- const PASSWORD = 'password';
303
- public function __construct() {
304
- parent::__construct ();
305
- $this->options = get_option ( 'swpsmtp_options' );
306
- }
307
- public function getPluginSlug() {
308
- return self::SLUG;
309
- }
310
- public function getPluginName() {
311
- return self::PLUGIN_NAME;
312
- }
313
- public function getMessageSenderEmail() {
314
- if (isset ( $this->options [self::MESSAGE_SENDER_EMAIL] ))
315
- return $this->options [self::MESSAGE_SENDER_EMAIL];
316
- }
317
- public function getMessageSenderName() {
318
- if (isset ( $this->options [self::MESSAGE_SENDER_NAME] ))
319
- return $this->options [self::MESSAGE_SENDER_NAME];
320
- }
321
- public function getHostname() {
322
- if (isset ( $this->options [self::SMTP_SETTINGS] [self::HOSTNAME] ))
323
- return $this->options [self::SMTP_SETTINGS] [self::HOSTNAME];
324
- }
325
- public function getPort() {
326
- if (isset ( $this->options [self::SMTP_SETTINGS] [self::PORT] ))
327
- return $this->options [self::SMTP_SETTINGS] [self::PORT];
328
- }
329
- public function getUsername() {
330
- if (isset ( $this->options [self::SMTP_SETTINGS] [self::USERNAME] ))
331
- return $this->options [self::SMTP_SETTINGS] [self::USERNAME];
332
- }
333
- public function getPassword() {
334
- if (isset ( $this->options [self::SMTP_SETTINGS] [self::PASSWORD] )) {
335
- // wpecommerce screwed the pooch
336
- $password = $this->options [self::SMTP_SETTINGS] [self::PASSWORD];
337
- if ( strlen ( $password ) ) {
338
- $decodedPw = base64_decode ( $password, true );
339
- $reencodedPw = base64_encode ( $decodedPw );
340
- if ($reencodedPw === $password) {
341
- // encoded
342
- return $decodedPw;
343
- } else {
344
- // not encoded
345
- return $password;
346
- }
347
- }
348
- }
349
- }
350
- public function getAuthenticationType() {
351
- if (isset ( $this->options [self::SMTP_SETTINGS] [self::AUTHENTICATION_TYPE] )) {
352
- switch ($this->options [self::SMTP_SETTINGS] [self::AUTHENTICATION_TYPE]) {
353
- case 'yes' :
354
- return PostmanOptions::AUTHENTICATION_TYPE_PLAIN;
355
- case 'no' :
356
- return PostmanOptions::AUTHENTICATION_TYPE_NONE;
357
- }
358
- }
359
- }
360
- public function getEncryptionType() {
361
- if (isset ( $this->options [self::SMTP_SETTINGS] [self::ENCRYPTION_TYPE] )) {
362
- switch ($this->options [self::SMTP_SETTINGS] [self::ENCRYPTION_TYPE]) {
363
- case 'ssl' :
364
- return PostmanOptions::SECURITY_TYPE_SMTPS;
365
- case 'tls' :
366
- return PostmanOptions::SECURITY_TYPE_STARTTLS;
367
- case 'none' :
368
- return PostmanOptions::SECURITY_TYPE_NONE;
369
- }
370
- }
371
- }
372
-
373
- /**
374
- * Get plugin's logo
375
- *
376
- * @since 2.1
377
- * @version 1.0
378
- */
379
- public function getPluginLogo() {
380
- return POST_SMTP_ASSETS . "images/logos/easy-wp-smtp.png";
381
- }
382
- }
383
- }
384
-
385
- if (! class_exists ( 'PostmanWpMailBankOptions' )) {
386
-
387
- /**
388
- * Import configuration from WP Mail Bank
389
- *
390
- * @author jasonhendriks
391
- *
392
- */
393
- class PostmanWpMailBankOptions extends PostmanAbstractPluginOptions implements PostmanPluginOptions {
394
- const SLUG = 'wp_mail_bank';
395
- const PLUGIN_NAME = 'WP Mail Bank';
396
- const MESSAGE_SENDER_EMAIL = 'sender_email';
397
- const MESSAGE_SENDER_NAME = 'sender_name';
398
- const HOSTNAME = 'hostname';
399
- const PORT = 'port';
400
- const ENCRYPTION_TYPE = 'enc_type';
401
- const AUTHENTICATION_TYPE = 'auth_type';
402
- const USERNAME = 'username';
403
- const PASSWORD = 'password';
404
- const MAILER_TYPE = 'mailer_type';
405
- public function __construct() {
406
- parent::__construct ();
407
- // data is stored in table wp_mail_meta
408
- // fields are id, from_name, from_email, mailer_type, return_path, return_email, smtp_host, smtp_port, word_wrap, encryption, smtp_keep_alive, authentication, smtp_username, smtp_password
409
- if( array_key_exists ( 'wp-mail-bank/wp-mail-bank.php', get_plugins () ) ) {
410
- global $wpdb;
411
- $wpdb->show_errors ();
412
- $wpdb->suppress_errors ();
413
- $mb_email_configuration_data = $wpdb->get_row(
414
- $wpdb->prepare(
415
- 'SELECT meta_value FROM ' . $wpdb->prefix . 'mail_bank_meta WHERE meta_key = %s', 'email_configuration'
416
- ), ARRAY_A
417
- );
418
- $mb_email_configuration_data = unserialize( $mb_email_configuration_data['meta_value'] );
419
-
420
- $this->options [self::MESSAGE_SENDER_EMAIL] = $mb_email_configuration_data[ self::MESSAGE_SENDER_EMAIL ];
421
- $this->options [self::MESSAGE_SENDER_NAME] = $mb_email_configuration_data[ self::MESSAGE_SENDER_NAME ];
422
- $this->options [self::HOSTNAME] = $mb_email_configuration_data[ self::HOSTNAME ];
423
- $this->options [self::PORT] = $mb_email_configuration_data[ self::PORT ];
424
- $this->options [self::ENCRYPTION_TYPE] = $mb_email_configuration_data[ self::ENCRYPTION_TYPE ];
425
- $this->options [self::AUTHENTICATION_TYPE] = $mb_email_configuration_data[ self::AUTHENTICATION_TYPE ];
426
- $this->options [self::USERNAME] = $mb_email_configuration_data[ self::USERNAME ];
427
- $this->options [self::PASSWORD] = base64_decode( $mb_email_configuration_data[ self::PASSWORD ] );
428
- $this->options [self::MAILER_TYPE] = $mb_email_configuration_data[ self::MAILER_TYPE ];
429
- }
430
-
431
- }
432
- public function getPluginSlug() {
433
- return self::SLUG;
434
- }
435
- public function getPluginName() {
436
- return self::PLUGIN_NAME;
437
- }
438
- public function getMessageSenderEmail() {
439
- if (isset ( $this->options [self::MESSAGE_SENDER_EMAIL] ))
440
- return $this->options [self::MESSAGE_SENDER_EMAIL];
441
- }
442
- public function getMessageSenderName() {
443
- if (isset ( $this->options [self::MESSAGE_SENDER_NAME] )) {
444
- return stripslashes ( htmlspecialchars_decode ( $this->options [self::MESSAGE_SENDER_NAME], ENT_QUOTES ) );
445
- }
446
- }
447
- public function getHostname() {
448
- if (isset ( $this->options [self::HOSTNAME] ))
449
- return $this->options [self::HOSTNAME];
450
- }
451
- public function getPort() {
452
- if (isset ( $this->options [self::PORT] ))
453
- return $this->options [self::PORT];
454
- }
455
- public function getUsername() {
456
- if (isset ( $this->options [self::AUTHENTICATION_TYPE] ) && isset ( $this->options [self::USERNAME] ))
457
- if ($this->options[self::AUTHENTICATION_TYPE] != 'none' )
458
- return $this->options [self::USERNAME];
459
- }
460
- public function getPassword() {
461
- if (isset ( $this->options [self::AUTHENTICATION_TYPE] ) && isset ( $this->options [self::PASSWORD] )) {
462
- if ($this->options [self::AUTHENTICATION_TYPE] != 'none' )
463
- return $this->options [self::PASSWORD];
464
- }
465
- }
466
- public function getAuthenticationType() {
467
- if (isset ( $this->options [self::AUTHENTICATION_TYPE] )) {
468
-
469
- switch( $this->options [self::AUTHENTICATION_TYPE] ) {
470
- case 'none':
471
- return PostmanOptions::AUTHENTICATION_TYPE_NONE;
472
-
473
- case 'plain':
474
- return PostmanOptions::AUTHENTICATION_TYPE_PLAIN;
475
-
476
- case 'login':
477
- return PostmanOptions::AUTHENTICATION_TYPE_LOGIN;
478
-
479
- case 'crammd5':
480
- return PostmanOptions::AUTHENTICATION_TYPE_CRAMMD5;
481
-
482
- case 'oauth2':
483
- return PostmanOptions::AUTHENTICATION_TYPE_OAUTH2;
484
- }
485
- }
486
- }
487
- public function getEncryptionType() {
488
- if (isset ( $this->options [self::MAILER_TYPE] )) {
489
- if ($this->options[self::MAILER_TYPE] == 'smtp') {
490
- switch ($this->options [self::ENCRYPTION_TYPE]) {
491
- case 'none' :
492
- return PostmanOptions::SECURITY_TYPE_NONE;
493
- case 'ssl' :
494
- return PostmanOptions::SECURITY_TYPE_SMTPS;
495
- case 'tls' :
496
- return PostmanOptions::SECURITY_TYPE_STARTTLS;
497
- }
498
- }
499
- }
500
- }
501
-
502
- /**
503
- * Get plugin's logo
504
- *
505
- * @since 2.1
506
- * @version 1.0
507
- */
508
- public function getPluginLogo() {
509
- return POST_SMTP_ASSETS . "images/logos/wp-mail-bank.png";
510
- }
511
- }
512
- }
513
-
514
- // "WP Mail SMTP" (aka "Email") - 300,000
515
- // each field is a new row in options : mail_from, mail_from_name, smtp_host, smtp_port, smtp_ssl, smtp_auth, smtp_user, smtp_pass
516
- // "Easy SMTP Mail" aka. "Webriti SMTP Mail" appears to share the data format of "WP Mail SMTP" so no need to create an Options class for it.
517
- //
518
- if (! class_exists ( 'PostmanWpMailSmtpOptions' )) {
519
- class PostmanWpMailSmtpOptions extends PostmanAbstractPluginOptions implements PostmanPluginOptions {
520
- const SLUG = 'wp_mail_smtp';
521
- const PLUGIN_NAME = 'WP Mail SMTP';
522
- const MESSAGE_SENDER_EMAIL = 'mail_from';
523
- const MESSAGE_SENDER_NAME = 'mail_from_name';
524
- const HOSTNAME = 'smtp_host';
525
- const PORT = 'smtp_port';
526
- const ENCRYPTION_TYPE = 'smtp_ssl';
527
- const AUTHENTICATION_TYPE = 'smtp_auth';
528
- const USERNAME = 'smtp_user';
529
- const PASSWORD = 'smtp_pass';
530
- public function __construct() {
531
- parent::__construct ();
532
- $this->options [self::MESSAGE_SENDER_EMAIL] = get_option ( self::MESSAGE_SENDER_EMAIL );
533
- $this->options [self::MESSAGE_SENDER_NAME] = get_option ( self::MESSAGE_SENDER_NAME );
534
- $this->options [self::HOSTNAME] = get_option ( self::HOSTNAME );
535
- $this->options [self::PORT] = get_option ( self::PORT );
536
- $this->options [self::ENCRYPTION_TYPE] = get_option ( self::ENCRYPTION_TYPE );
537
- $this->options [self::AUTHENTICATION_TYPE] = get_option ( self::AUTHENTICATION_TYPE );
538
- $this->options [self::USERNAME] = get_option ( self::USERNAME );
539
- $this->options [self::PASSWORD] = get_option ( self::PASSWORD );
540
- }
541
- public function getPluginSlug() {
542
- return self::SLUG;
543
- }
544
- public function getPluginName() {
545
- return self::PLUGIN_NAME;
546
- }
547
- public function getMessageSenderEmail() {
548
- if (isset ( $this->options [self::MESSAGE_SENDER_EMAIL] ))
549
- return $this->options [self::MESSAGE_SENDER_EMAIL];
550
- }
551
- public function getMessageSenderName() {
552
- if (isset ( $this->options [self::MESSAGE_SENDER_NAME] ))
553
- return $this->options [self::MESSAGE_SENDER_NAME];
554
- }
555
- public function getHostname() {
556
- if (isset ( $this->options [self::HOSTNAME] ))
557
- return $this->options [self::HOSTNAME];
558
- }
559
- public function getPort() {
560
- if (isset ( $this->options [self::PORT] ))
561
- return $this->options [self::PORT];
562
- }
563
- public function getUsername() {
564
- if (isset ( $this->options [self::USERNAME] ))
565
- return $this->options [self::USERNAME];
566
- }
567
- public function getPassword() {
568
- if (isset ( $this->options [self::PASSWORD] ))
569
- return $this->options [self::PASSWORD];
570
- }
571
- public function getAuthenticationType() {
572
- if (isset ( $this->options [self::AUTHENTICATION_TYPE] )) {
573
- switch ($this->options [self::AUTHENTICATION_TYPE]) {
574
- case 'true' :
575
- return PostmanOptions::AUTHENTICATION_TYPE_PLAIN;
576
- case 'false' :
577
- return PostmanOptions::AUTHENTICATION_TYPE_NONE;
578
- }
579
- }
580
- }
581
- public function getEncryptionType() {
582
- if (isset ( $this->options [self::ENCRYPTION_TYPE] )) {
583
- switch ($this->options [self::ENCRYPTION_TYPE]) {
584
- case 'ssl' :
585
- return PostmanOptions::SECURITY_TYPE_SMTPS;
586
- case 'tls' :
587
- return PostmanOptions::SECURITY_TYPE_STARTTLS;
588
- case 'none' :
589
- return PostmanOptions::SECURITY_TYPE_NONE;
590
- }
591
- }
592
- }
593
-
594
- /**
595
- * Get plugin's logo
596
- *
597
- * @since 2.1
598
- * @version 1.0
599
- */
600
- public function getPluginLogo() {
601
- return POST_SMTP_ASSETS . "images/logos/wp-mail-smtp.png";
602
- }
603
- }
604
- }
605
-
606
- // WP SMTP - 40,000
607
- if (! class_exists ( 'PostmanWpSmtpOptions' )) {
608
- class PostmanWpSmtpOptions extends PostmanAbstractPluginOptions implements PostmanPluginOptions {
609
- const SLUG = 'wp_smtp'; // god these names are terrible
610
- const PLUGIN_NAME = 'WP SMTP';
611
- const MESSAGE_SENDER_EMAIL = 'from';
612
- const MESSAGE_SENDER_NAME = 'fromname';
613
- const HOSTNAME = 'host';
614
- const PORT = 'port';
615
- const ENCRYPTION_TYPE = 'smtpsecure';
616
- const AUTHENTICATION_TYPE = 'smtpauth';
617
- const USERNAME = 'username';
618
- const PASSWORD = 'password';
619
- public function __construct() {
620
- parent::__construct ();
621
- $this->options = get_option ( 'wp_smtp_options' );
622
- }
623
- public function getPluginSlug() {
624
- return self::SLUG;
625
- }
626
- public function getPluginName() {
627
- return self::PLUGIN_NAME;
628
- }
629
- public function getMessageSenderEmail() {
630
- if (isset ( $this->options [self::MESSAGE_SENDER_EMAIL] ))
631
- return $this->options [self::MESSAGE_SENDER_EMAIL];
632
- }
633
- public function getMessageSenderName() {
634
- if (isset ( $this->options [self::MESSAGE_SENDER_NAME] ))
635
- return $this->options [self::MESSAGE_SENDER_NAME];
636
- }
637
- public function getHostname() {
638
- if (isset ( $this->options [self::HOSTNAME] ))
639
- return $this->options [self::HOSTNAME];
640
- }
641
- public function getPort() {
642
- if (isset ( $this->options [self::PORT] ))
643
- return $this->options [self::PORT];
644
- }
645
- public function getUsername() {
646
- if (isset ( $this->options [self::USERNAME] ))
647
- return $this->options [self::USERNAME];
648
- }
649
- public function getPassword() {
650
- if (isset ( $this->options [self::PASSWORD] ))
651
- return $this->options [self::PASSWORD];
652
- }
653
- public function getAuthenticationType() {
654
- if (isset ( $this->options [self::AUTHENTICATION_TYPE] )) {
655
- switch ($this->options [self::AUTHENTICATION_TYPE]) {
656
- case 'yes' :
657
- return PostmanOptions::AUTHENTICATION_TYPE_PLAIN;
658
- case 'no' :
659
- return PostmanOptions::AUTHENTICATION_TYPE_NONE;
660
- }
661
- }
662
- }
663
- public function getEncryptionType() {
664
- if (isset ( $this->options [self::ENCRYPTION_TYPE] )) {
665
- switch ($this->options [self::ENCRYPTION_TYPE]) {
666
- case 'ssl' :
667
- return PostmanOptions::SECURITY_TYPE_SMTPS;
668
- case 'tls' :
669
- return PostmanOptions::SECURITY_TYPE_STARTTLS;
670
- case '' :
671
- return PostmanOptions::SECURITY_TYPE_NONE;
672
- }
673
- }
674
- }
675
-
676
- /**
677
- * Get plugin's logo
678
- *
679
- * @since 2.1
680
- * @version 1.0
681
- */
682
- public function getPluginLogo() {
683
- return POST_SMTP_ASSETS . "images/logos/wp-smtp.png";
684
- }
685
- }
 
 
 
 
 
 
686
  }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ if (! interface_exists ( 'PostmanPluginOptions' )) {
7
+ interface PostmanPluginOptions {
8
+ public function getPluginSlug();
9
+ public function getPluginName();
10
+ public function isImportable();
11
+ public function getHostname();
12
+ public function getPort();
13
+ public function getMessageSenderEmail();
14
+ public function getMessageSenderName();
15
+ public function getAuthenticationType();
16
+ public function getEncryptionType();
17
+ public function getUsername();
18
+ public function getPassword();
19
+ /**
20
+ * Get plugin's logo
21
+ *
22
+ * @since 2.1
23
+ * @version 1.0
24
+ */
25
+ public function getPluginLogo();
26
+ }
27
+ }
28
+ if (! class_exists ( 'PostmanImportableConfiguration' )) {
29
+
30
+ /**
31
+ * This class instantiates the Connectors for new users to Postman.
32
+ * It determines which Connectors can supply configuration data
33
+ *
34
+ * @author jasonhendriks
35
+ *
36
+ */
37
+ class PostmanImportableConfiguration {
38
+ private $lazyInit;
39
+ private $availableOptions;
40
+ private $importAvailable;
41
+ private $logger;
42
+ function __construct() {
43
+ $this->logger = new PostmanLogger ( get_class ( $this ) );
44
+ }
45
+ function init() {
46
+ if (! $this->lazyInit) {
47
+ $this->queueIfAvailable ( new PostmanEasyWpSmtpOptions () );
48
+ $this->queueIfAvailable ( new PostmanWpSmtpOptions () );
49
+ $this->queueIfAvailable ( new PostmanWpMailBankOptions () );
50
+ $this->queueIfAvailable ( new PostmanWpMailSmtpOptions () );
51
+ $this->queueIfAvailable ( new PostmanCimySwiftSmtpOptions () );
52
+ $this->queueIfAvailable ( new PostmanConfigureSmtpOptions () );
53
+ }
54
+ $this->lazyInit = true;
55
+ }
56
+ private function queueIfAvailable(PostmanPluginOptions $options) {
57
+ $slug = $options->getPluginSlug ();
58
+ if ($options->isImportable ()) {
59
+ $this->availableOptions [$slug] = $options;
60
+ $this->importAvailable = true;
61
+ $this->logger->debug ( $slug . ' is importable' );
62
+ } else {
63
+ $this->logger->debug ( $slug . ' is not importable' );
64
+ }
65
+ }
66
+ public function getAvailableOptions() {
67
+ $this->init ();
68
+ return $this->availableOptions;
69
+ }
70
+ public function isImportAvailable() {
71
+ $this->init ();
72
+ return $this->importAvailable;
73
+ }
74
+ }
75
+ }
76
+
77
+ if (! class_exists ( 'PostmanAbstractPluginOptions' )) {
78
+
79
+ /**
80
+ *
81
+ * @author jasonhendriks
82
+ */
83
+ abstract class PostmanAbstractPluginOptions implements PostmanPluginOptions {
84
+ protected $options;
85
+ protected $logger;
86
+ public function __construct() {
87
+ $this->logger = new PostmanLogger ( get_class ( $this ) );
88
+ }
89
+ public function isValid() {
90
+ $valid = true;
91
+ $host = $this->getHostname ();
92
+ $port = $this->getPort ();
93
+ $fromEmail = $this->getMessageSenderEmail ();
94
+ $fromName = $this->getMessageSenderName ();
95
+ $auth = $this->getAuthenticationType ();
96
+ $enc = $this->getEncryptionType ();
97
+ $username = $this->getUsername ();
98
+ $password = $this->getPassword ();
99
+ $valid &= ! empty ( $host );
100
+ $this->logger->trace ( 'host ok ' . $valid );
101
+ $valid &= ! empty ( $port ) && absint ( $port ) > 0 && absint ( $port ) <= 65535;
102
+ $this->logger->trace ( 'port ok ' . $valid );
103
+ $valid &= ! empty ( $fromEmail );
104
+ $this->logger->trace ( 'from email ok ' . $valid );
105
+ $valid &= ! empty ( $fromName );
106
+ $this->logger->trace ( 'from name ok ' . $valid );
107
+ $valid &= ! empty ( $auth );
108
+ $this->logger->trace ( 'auth ok ' . $valid );
109
+ $valid &= ! empty ( $enc );
110
+ $this->logger->trace ( 'enc ok ' . $valid );
111
+ if ($auth != PostmanOptions::AUTHENTICATION_TYPE_NONE) {
112
+ $valid &= ! empty ( $username );
113
+ $valid &= ! empty ( $password );
114
+ }
115
+ $this->logger->trace ( 'user/pass ok ' . $valid );
116
+ return $valid;
117
+ }
118
+ public function isImportable() {
119
+ return $this->isValid ();
120
+ }
121
+ }
122
+ }
123
+
124
+ if (! class_exists ( 'PostmanConfigureSmtpOptions' )) {
125
+ // ConfigureSmtp (aka "SMTP") - 80,000
126
+ class PostmanConfigureSmtpOptions extends PostmanAbstractPluginOptions {
127
+ const SLUG = 'configure_smtp';
128
+ const PLUGIN_NAME = 'Configure SMTP';
129
+ const MESSAGE_SENDER_EMAIL = 'from_email';
130
+ const MESSAGE_SENDER_NAME = 'from_name';
131
+ const HOSTNAME = 'host';
132
+ const PORT = 'port';
133
+ const AUTHENTICATION_TYPE = 'smtp_auth';
134
+ const ENCRYPTION_TYPE = 'smtp_secure';
135
+ const USERNAME = 'smtp_user';
136
+ const PASSWORD = 'smtp_pass';
137
+ public function __construct() {
138
+ parent::__construct ();
139
+ $this->options = get_option ( 'c2c_configure_smtp' );
140
+ }
141
+ public function getPluginSlug() {
142
+ return self::SLUG;
143
+ }
144
+ public function getPluginName() {
145
+ return self::PLUGIN_NAME;
146
+ }
147
+ public function getMessageSenderEmail() {
148
+ if (isset ( $this->options [self::MESSAGE_SENDER_EMAIL] ))
149
+ return $this->options [self::MESSAGE_SENDER_EMAIL];
150
+ }
151
+ public function getMessageSenderName() {
152
+ if (isset ( $this->options [self::MESSAGE_SENDER_NAME] ))
153
+ return $this->options [self::MESSAGE_SENDER_NAME];
154
+ }
155
+ public function getHostname() {
156
+ if (isset ( $this->options [self::HOSTNAME] ))
157
+ return $this->options [self::HOSTNAME];
158
+ }
159
+ public function getPort() {
160
+ if (isset ( $this->options [self::PORT] ))
161
+ return $this->options [self::PORT];
162
+ }
163
+ public function getUsername() {
164
+ if (isset ( $this->options [self::USERNAME] ))
165
+ return $this->options [self::USERNAME];
166
+ }
167
+ public function getPassword() {
168
+ if (isset ( $this->options [self::PASSWORD] ))
169
+ return $this->options [self::PASSWORD];
170
+ }
171
+ public function getAuthenticationType() {
172
+ if (isset ( $this->options [self::AUTHENTICATION_TYPE] )) {
173
+ if ($this->options [self::AUTHENTICATION_TYPE] == 1) {
174
+ return PostmanOptions::AUTHENTICATION_TYPE_PLAIN;
175
+ } else {
176
+ return PostmanOptions::AUTHENTICATION_TYPE_NONE;
177
+ }
178
+ }
179
+ }
180
+ public function getEncryptionType() {
181
+ if (isset ( $this->options [self::ENCRYPTION_TYPE] )) {
182
+ switch ($this->options [self::ENCRYPTION_TYPE]) {
183
+ case 'ssl' :
184
+ return PostmanOptions::SECURITY_TYPE_SMTPS;
185
+ case 'tls' :
186
+ return PostmanOptions::SECURITY_TYPE_STARTTLS;
187
+ case '' :
188
+ return PostmanOptions::SECURITY_TYPE_NONE;
189
+ }
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Get plugin's logo
195
+ *
196
+ * @since 2.1
197
+ * @version 1.0
198
+ */
199
+ public function getPluginLogo() {
200
+ return POST_SMTP_ASSETS . "images/logos/configure-smtp.png";
201
+ }
202
+ }
203
+ }
204
+
205
+ if (! class_exists ( 'PostmanCimySwiftSmtpOptions' )) {
206
+ // Cimy Swift - 9,000
207
+ class PostmanCimySwiftSmtpOptions extends PostmanAbstractPluginOptions {
208
+ const SLUG = 'cimy_swift_smtp';
209
+ const PLUGIN_NAME = 'Cimy Swift SMTP';
210
+ const MESSAGE_SENDER_EMAIL = 'sender_mail';
211
+ const MESSAGE_SENDER_NAME = 'sender_name';
212
+ const HOSTNAME = 'server';
213
+ const PORT = 'port';
214
+ const ENCRYPTION_TYPE = 'ssl';
215
+ const USERNAME = 'username';
216
+ const PASSWORD = 'password';
217
+ public function __construct() {
218
+ parent::__construct ();
219
+ $this->options = get_option ( 'cimy_swift_smtp_options' );
220
+ }
221
+ public function getPluginSlug() {
222
+ return self::SLUG;
223
+ }
224
+ public function getPluginName() {
225
+ return self::PLUGIN_NAME;
226
+ }
227
+ public function getMessageSenderEmail() {
228
+ if (isset ( $this->options [self::MESSAGE_SENDER_EMAIL] ))
229
+ return $this->options [self::MESSAGE_SENDER_EMAIL];
230
+ }
231
+ public function getMessageSenderName() {
232
+ if (isset ( $this->options [self::MESSAGE_SENDER_NAME] ))
233
+ return $this->options [self::MESSAGE_SENDER_NAME];
234
+ }
235
+ public function getHostname() {
236
+ if (isset ( $this->options [self::HOSTNAME] ))
237
+ return $this->options [self::HOSTNAME];
238
+ }
239
+ public function getPort() {
240
+ if (isset ( $this->options [self::PORT] ))
241
+ return $this->options [self::PORT];
242
+ }
243
+ public function getUsername() {
244
+ if (isset ( $this->options [self::USERNAME] ))
245
+ return $this->options [self::USERNAME];
246
+ }
247
+ public function getPassword() {
248
+ if (isset ( $this->options [self::PASSWORD] ))
249
+ return $this->options [self::PASSWORD];
250
+ }
251
+ public function getAuthenticationType() {
252
+ if (! empty ( $this->options [self::USERNAME] ) && ! empty ( $this->options [self::PASSWORD] )) {
253
+ return PostmanOptions::AUTHENTICATION_TYPE_PLAIN;
254
+ } else {
255
+ return PostmanOptions::AUTHENTICATION_TYPE_NONE;
256
+ }
257
+ }
258
+ public function getEncryptionType() {
259
+ if (isset ( $this->options [self::ENCRYPTION_TYPE] )) {
260
+ switch ($this->options [self::ENCRYPTION_TYPE]) {
261
+ case 'ssl' :
262
+ return PostmanOptions::SECURITY_TYPE_SMTPS;
263
+ case 'tls' :
264
+ return PostmanOptions::SECURITY_TYPE_STARTTLS;
265
+ case '' :
266
+ return PostmanOptions::SECURITY_TYPE_NONE;
267
+ }
268
+ }
269
+ }
270
+
271
+ /**
272
+ * Get plugin's logo
273
+ *
274
+ * @since 2.1
275
+ * @version 1.0
276
+ */
277
+ public function getPluginLogo() {
278
+ return POST_SMTP_ASSETS . "images/logos/php.png";
279
+ }
280
+ }
281
+ }
282
+
283
+ // Easy WP SMTP - 40,000
284
+ if (! class_exists ( 'PostmanEasyWpSmtpOptions' )) {
285
+
286
+ /**
287
+ * Imports Easy WP SMTP options into Postman
288
+ *
289
+ * @author jasonhendriks
290
+ */
291
+ class PostmanEasyWpSmtpOptions extends PostmanAbstractPluginOptions implements PostmanPluginOptions {
292
+ const SLUG = 'easy_wp_smtp';
293
+ const PLUGIN_NAME = 'Easy WP SMTP';
294
+ const SMTP_SETTINGS = 'smtp_settings';
295
+ const MESSAGE_SENDER_EMAIL = 'from_email_field';
296
+ const MESSAGE_SENDER_NAME = 'from_name_field';
297
+ const HOSTNAME = 'host';
298
+ const PORT = 'port';
299
+ const ENCRYPTION_TYPE = 'type_encryption';
300
+ const AUTHENTICATION_TYPE = 'autentication';
301
+ const USERNAME = 'username';
302
+ const PASSWORD = 'password';
303
+ public function __construct() {
304
+ parent::__construct ();
305
+ $this->options = get_option ( 'swpsmtp_options' );
306
+ }
307
+ public function getPluginSlug() {
308
+ return self::SLUG;
309
+ }
310
+ public function getPluginName() {
311
+ return self::PLUGIN_NAME;
312
+ }
313
+ public function getMessageSenderEmail() {
314
+ if (isset ( $this->options [self::MESSAGE_SENDER_EMAIL] ))
315
+ return $this->options [self::MESSAGE_SENDER_EMAIL];
316
+ }
317
+ public function getMessageSenderName() {
318
+ if (isset ( $this->options [self::MESSAGE_SENDER_NAME] ))
319
+ return $this->options [self::MESSAGE_SENDER_NAME];
320
+ }
321
+ public function getHostname() {
322
+ if (isset ( $this->options [self::SMTP_SETTINGS] [self::HOSTNAME] ))
323
+ return $this->options [self::SMTP_SETTINGS] [self::HOSTNAME];
324
+ }
325
+ public function getPort() {
326
+ if (isset ( $this->options [self::SMTP_SETTINGS] [self::PORT] ))
327
+ return $this->options [self::SMTP_SETTINGS] [self::PORT];
328
+ }
329
+ public function getUsername() {
330
+ if (isset ( $this->options [self::SMTP_SETTINGS] [self::USERNAME] ))
331
+ return $this->options [self::SMTP_SETTINGS] [self::USERNAME];
332
+ }
333
+ public function getPassword() {
334
+ if (isset ( $this->options [self::SMTP_SETTINGS] [self::PASSWORD] )) {
335
+ // wpecommerce screwed the pooch
336
+ $password = $this->options [self::SMTP_SETTINGS] [self::PASSWORD];
337
+ if ( strlen ( $password ) ) {
338
+ $decodedPw = base64_decode ( $password, true );
339
+ $reencodedPw = base64_encode ( $decodedPw );
340
+ if ($reencodedPw === $password) {
341
+ // encoded
342
+ return $decodedPw;
343
+ } else {
344
+ // not encoded
345
+ return $password;
346
+ }
347
+ }
348
+ }
349
+ }
350
+ public function getAuthenticationType() {
351
+ if (isset ( $this->options [self::SMTP_SETTINGS] [self::AUTHENTICATION_TYPE] )) {
352
+ switch ($this->options [self::SMTP_SETTINGS] [self::AUTHENTICATION_TYPE]) {
353
+ case 'yes' :
354
+ return PostmanOptions::AUTHENTICATION_TYPE_PLAIN;
355
+ case 'no' :
356
+ return PostmanOptions::AUTHENTICATION_TYPE_NONE;
357
+ }
358
+ }
359
+ }
360
+ public function getEncryptionType() {
361
+ if (isset ( $this->options [self::SMTP_SETTINGS] [self::ENCRYPTION_TYPE] )) {
362
+ switch ($this->options [self::SMTP_SETTINGS] [self::ENCRYPTION_TYPE]) {
363
+ case 'ssl' :
364
+ return PostmanOptions::SECURITY_TYPE_SMTPS;
365
+ case 'tls' :
366
+ return PostmanOptions::SECURITY_TYPE_STARTTLS;
367
+ case 'none' :
368
+ return PostmanOptions::SECURITY_TYPE_NONE;
369
+ }
370
+ }
371
+ }
372
+
373
+ /**
374
+ * Get plugin's logo
375
+ *
376
+ * @since 2.1
377
+ * @version 1.0
378
+ */
379
+ public function getPluginLogo() {
380
+ return POST_SMTP_ASSETS . "images/logos/easy-wp-smtp.png";
381
+ }
382
+ }
383
+ }
384
+
385
+ if (! class_exists ( 'PostmanWpMailBankOptions' )) {
386
+
387
+ /**
388
+ * Import configuration from WP Mail Bank
389
+ *
390
+ * @author jasonhendriks
391
+ *
392
+ */
393
+ class PostmanWpMailBankOptions extends PostmanAbstractPluginOptions implements PostmanPluginOptions {
394
+ const SLUG = 'wp_mail_bank';
395
+ const PLUGIN_NAME = 'WP Mail Bank';
396
+ const MESSAGE_SENDER_EMAIL = 'sender_email';
397
+ const MESSAGE_SENDER_NAME = 'sender_name';
398
+ const HOSTNAME = 'hostname';
399
+ const PORT = 'port';
400
+ const ENCRYPTION_TYPE = 'enc_type';
401
+ const AUTHENTICATION_TYPE = 'auth_type';
402
+ const USERNAME = 'username';
403
+ const PASSWORD = 'password';
404
+ const MAILER_TYPE = 'mailer_type';
405
+ public function __construct() {
406
+ parent::__construct ();
407
+ // data is stored in table wp_mail_meta
408
+ // fields are id, from_name, from_email, mailer_type, return_path, return_email, smtp_host, smtp_port, word_wrap, encryption, smtp_keep_alive, authentication, smtp_username, smtp_password
409
+ if( array_key_exists ( 'wp-mail-bank/wp-mail-bank.php', get_plugins () ) ) {
410
+ global $wpdb;
411
+ $wpdb->show_errors ();
412
+ $wpdb->suppress_errors ();
413
+ $mb_email_configuration_data = $wpdb->get_row(
414
+ $wpdb->prepare(
415
+ 'SELECT meta_value FROM ' . $wpdb->prefix . 'mail_bank_meta WHERE meta_key = %s', 'email_configuration'
416
+ ), ARRAY_A
417
+ );
418
+
419
+ if( isset( $mb_email_configuration_data['meta_value'] ) ) {
420
+
421
+ $mb_email_configuration_data = unserialize( $mb_email_configuration_data['meta_value'] );
422
+
423
+ $this->options [self::MESSAGE_SENDER_EMAIL] = $mb_email_configuration_data[ self::MESSAGE_SENDER_EMAIL ];
424
+ $this->options [self::MESSAGE_SENDER_NAME] = $mb_email_configuration_data[ self::MESSAGE_SENDER_NAME ];
425
+ $this->options [self::HOSTNAME] = $mb_email_configuration_data[ self::HOSTNAME ];
426
+ $this->options [self::PORT] = $mb_email_configuration_data[ self::PORT ];
427
+ $this->options [self::ENCRYPTION_TYPE] = $mb_email_configuration_data[ self::ENCRYPTION_TYPE ];
428
+ $this->options [self::AUTHENTICATION_TYPE] = $mb_email_configuration_data[ self::AUTHENTICATION_TYPE ];
429
+ $this->options [self::USERNAME] = $mb_email_configuration_data[ self::USERNAME ];
430
+ $this->options [self::PASSWORD] = base64_decode( $mb_email_configuration_data[ self::PASSWORD ] );
431
+ $this->options [self::MAILER_TYPE] = $mb_email_configuration_data[ self::MAILER_TYPE ];
432
+
433
+ }
434
+
435
+ }
436
+
437
+ }
438
+ public function getPluginSlug() {
439
+ return self::SLUG;
440
+ }
441
+ public function getPluginName() {
442
+ return self::PLUGIN_NAME;
443
+ }
444
+ public function getMessageSenderEmail() {
445
+ if (isset ( $this->options [self::MESSAGE_SENDER_EMAIL] ))
446
+ return $this->options [self::MESSAGE_SENDER_EMAIL];
447
+ }
448
+ public function getMessageSenderName() {
449
+ if (isset ( $this->options [self::MESSAGE_SENDER_NAME] )) {
450
+ return stripslashes ( htmlspecialchars_decode ( $this->options [self::MESSAGE_SENDER_NAME], ENT_QUOTES ) );
451
+ }
452
+ }
453
+ public function getHostname() {
454
+ if (isset ( $this->options [self::HOSTNAME] ))
455
+ return $this->options [self::HOSTNAME];
456
+ }
457
+ public function getPort() {
458
+ if (isset ( $this->options [self::PORT] ))
459
+ return $this->options [self::PORT];
460
+ }
461
+ public function getUsername() {
462
+ if (isset ( $this->options [self::AUTHENTICATION_TYPE] ) && isset ( $this->options [self::USERNAME] ))
463
+ if ($this->options[self::AUTHENTICATION_TYPE] != 'none' )
464
+ return $this->options [self::USERNAME];
465
+ }
466
+ public function getPassword() {
467
+ if (isset ( $this->options [self::AUTHENTICATION_TYPE] ) && isset ( $this->options [self::PASSWORD] )) {
468
+ if ($this->options [self::AUTHENTICATION_TYPE] != 'none' )
469
+ return $this->options [self::PASSWORD];
470
+ }
471
+ }
472
+ public function getAuthenticationType() {
473
+ if (isset ( $this->options [self::AUTHENTICATION_TYPE] )) {
474
+
475
+ switch( $this->options [self::AUTHENTICATION_TYPE] ) {
476
+ case 'none':
477
+ return PostmanOptions::AUTHENTICATION_TYPE_NONE;
478
+
479
+ case 'plain':
480
+ return PostmanOptions::AUTHENTICATION_TYPE_PLAIN;
481
+
482
+ case 'login':
483
+ return PostmanOptions::AUTHENTICATION_TYPE_LOGIN;
484
+
485
+ case 'crammd5':
486
+ return PostmanOptions::AUTHENTICATION_TYPE_CRAMMD5;
487
+
488
+ case 'oauth2':
489
+ return PostmanOptions::AUTHENTICATION_TYPE_OAUTH2;
490
+ }
491
+ }
492
+ }
493
+ public function getEncryptionType() {
494
+ if (isset ( $this->options [self::MAILER_TYPE] )) {
495
+ if ($this->options[self::MAILER_TYPE] == 'smtp') {
496
+ switch ($this->options [self::ENCRYPTION_TYPE]) {
497
+ case 'none' :
498
+ return PostmanOptions::SECURITY_TYPE_NONE;
499
+ case 'ssl' :
500
+ return PostmanOptions::SECURITY_TYPE_SMTPS;
501
+ case 'tls' :
502
+ return PostmanOptions::SECURITY_TYPE_STARTTLS;
503
+ }
504
+ }
505
+ }
506
+ }
507
+
508
+ /**
509
+ * Get plugin's logo
510
+ *
511
+ * @since 2.1
512
+ * @version 1.0
513
+ */
514
+ public function getPluginLogo() {
515
+ return POST_SMTP_ASSETS . "images/logos/wp-mail-bank.png";
516
+ }
517
+ }
518
+ }
519
+
520
+ // "WP Mail SMTP" (aka "Email") - 300,000
521
+ // each field is a new row in options : mail_from, mail_from_name, smtp_host, smtp_port, smtp_ssl, smtp_auth, smtp_user, smtp_pass
522
+ // "Easy SMTP Mail" aka. "Webriti SMTP Mail" appears to share the data format of "WP Mail SMTP" so no need to create an Options class for it.
523
+ //
524
+ if (! class_exists ( 'PostmanWpMailSmtpOptions' )) {
525
+ class PostmanWpMailSmtpOptions extends PostmanAbstractPluginOptions implements PostmanPluginOptions {
526
+ const SLUG = 'wp_mail_smtp';
527
+ const PLUGIN_NAME = 'WP Mail SMTP';
528
+ const MESSAGE_SENDER_EMAIL = 'mail_from';
529
+ const MESSAGE_SENDER_NAME = 'mail_from_name';
530
+ const HOSTNAME = 'smtp_host';
531
+ const PORT = 'smtp_port';
532
+ const ENCRYPTION_TYPE = 'smtp_ssl';
533
+ const AUTHENTICATION_TYPE = 'smtp_auth';
534
+ const USERNAME = 'smtp_user';
535
+ const PASSWORD = 'smtp_pass';
536
+ public function __construct() {
537
+ parent::__construct ();
538
+ $this->options [self::MESSAGE_SENDER_EMAIL] = get_option ( self::MESSAGE_SENDER_EMAIL );
539
+ $this->options [self::MESSAGE_SENDER_NAME] = get_option ( self::MESSAGE_SENDER_NAME );
540
+ $this->options [self::HOSTNAME] = get_option ( self::HOSTNAME );
541
+ $this->options [self::PORT] = get_option ( self::PORT );
542
+ $this->options [self::ENCRYPTION_TYPE] = get_option ( self::ENCRYPTION_TYPE );
543
+ $this->options [self::AUTHENTICATION_TYPE] = get_option ( self::AUTHENTICATION_TYPE );
544
+ $this->options [self::USERNAME] = get_option ( self::USERNAME );
545
+ $this->options [self::PASSWORD] = get_option ( self::PASSWORD );
546
+ }
547
+ public function getPluginSlug() {
548
+ return self::SLUG;
549
+ }
550
+ public function getPluginName() {
551
+ return self::PLUGIN_NAME;
552
+ }
553
+ public function getMessageSenderEmail() {
554
+ if (isset ( $this->options [self::MESSAGE_SENDER_EMAIL] ))
555
+ return $this->options [self::MESSAGE_SENDER_EMAIL];
556
+ }
557
+ public function getMessageSenderName() {
558
+ if (isset ( $this->options [self::MESSAGE_SENDER_NAME] ))
559
+ return $this->options [self::MESSAGE_SENDER_NAME];
560
+ }
561
+ public function getHostname() {
562
+ if (isset ( $this->options [self::HOSTNAME] ))
563
+ return $this->options [self::HOSTNAME];
564
+ }
565
+ public function getPort() {
566
+ if (isset ( $this->options [self::PORT] ))
567
+ return $this->options [self::PORT];
568
+ }
569
+ public function getUsername() {
570
+ if (isset ( $this->options [self::USERNAME] ))
571
+ return $this->options [self::USERNAME];
572
+ }
573
+ public function getPassword() {
574
+ if (isset ( $this->options [self::PASSWORD] ))
575
+ return $this->options [self::PASSWORD];
576
+ }
577
+ public function getAuthenticationType() {
578
+ if (isset ( $this->options [self::AUTHENTICATION_TYPE] )) {
579
+ switch ($this->options [self::AUTHENTICATION_TYPE]) {
580
+ case 'true' :
581
+ return PostmanOptions::AUTHENTICATION_TYPE_PLAIN;
582
+ case 'false' :
583
+ return PostmanOptions::AUTHENTICATION_TYPE_NONE;
584
+ }
585
+ }
586
+ }
587
+ public function getEncryptionType() {
588
+ if (isset ( $this->options [self::ENCRYPTION_TYPE] )) {
589
+ switch ($this->options [self::ENCRYPTION_TYPE]) {
590
+ case 'ssl' :
591
+ return PostmanOptions::SECURITY_TYPE_SMTPS;
592
+ case 'tls' :
593
+ return PostmanOptions::SECURITY_TYPE_STARTTLS;
594
+ case 'none' :
595
+ return PostmanOptions::SECURITY_TYPE_NONE;
596
+ }
597
+ }
598
+ }
599
+
600
+ /**
601
+ * Get plugin's logo
602
+ *
603
+ * @since 2.1
604
+ * @version 1.0
605
+ */
606
+ public function getPluginLogo() {
607
+ return POST_SMTP_ASSETS . "images/logos/wp-mail-smtp.png";
608
+ }
609
+ }
610
+ }
611
+
612
+ // WP SMTP - 40,000
613
+ if (! class_exists ( 'PostmanWpSmtpOptions' )) {
614
+ class PostmanWpSmtpOptions extends PostmanAbstractPluginOptions implements PostmanPluginOptions {
615
+ const SLUG = 'wp_smtp'; // god these names are terrible
616
+ const PLUGIN_NAME = 'WP SMTP';
617
+ const MESSAGE_SENDER_EMAIL = 'from';
618
+ const MESSAGE_SENDER_NAME = 'fromname';
619
+ const HOSTNAME = 'host';
620
+ const PORT = 'port';
621
+ const ENCRYPTION_TYPE = 'smtpsecure';
622
+ const AUTHENTICATION_TYPE = 'smtpauth';
623
+ const USERNAME = 'username';
624
+ const PASSWORD = 'password';
625
+ public function __construct() {
626
+ parent::__construct ();
627
+ $this->options = get_option ( 'wp_smtp_options' );
628
+ }
629
+ public function getPluginSlug() {
630
+ return self::SLUG;
631
+ }
632
+ public function getPluginName() {
633
+ return self::PLUGIN_NAME;
634
+ }
635
+ public function getMessageSenderEmail() {
636
+ if (isset ( $this->options [self::MESSAGE_SENDER_EMAIL] ))
637
+ return $this->options [self::MESSAGE_SENDER_EMAIL];
638
+ }
639
+ public function getMessageSenderName() {
640
+ if (isset ( $this->options [self::MESSAGE_SENDER_NAME] ))
641
+ return $this->options [self::MESSAGE_SENDER_NAME];
642
+ }
643
+ public function getHostname() {
644
+ if (isset ( $this->options [self::HOSTNAME] ))
645
+ return $this->options [self::HOSTNAME];
646
+ }
647
+ public function getPort() {
648
+ if (isset ( $this->options [self::PORT] ))
649
+ return $this->options [self::PORT];
650
+ }
651
+ public function getUsername() {
652
+ if (isset ( $this->options [self::USERNAME] ))
653
+ return $this->options [self::USERNAME];
654
+ }
655
+ public function getPassword() {
656
+ if (isset ( $this->options [self::PASSWORD] ))
657
+ return $this->options [self::PASSWORD];
658
+ }
659
+ public function getAuthenticationType() {
660
+ if (isset ( $this->options [self::AUTHENTICATION_TYPE] )) {
661
+ switch ($this->options [self::AUTHENTICATION_TYPE]) {
662
+ case 'yes' :
663
+ return PostmanOptions::AUTHENTICATION_TYPE_PLAIN;
664
+ case 'no' :
665
+ return PostmanOptions::AUTHENTICATION_TYPE_NONE;
666
+ }
667
+ }
668
+ }
669
+ public function getEncryptionType() {
670
+ if (isset ( $this->options [self::ENCRYPTION_TYPE] )) {
671
+ switch ($this->options [self::ENCRYPTION_TYPE]) {
672
+ case 'ssl' :
673
+ return PostmanOptions::SECURITY_TYPE_SMTPS;
674
+ case 'tls' :
675
+ return PostmanOptions::SECURITY_TYPE_STARTTLS;
676
+ case '' :
677
+ return PostmanOptions::SECURITY_TYPE_NONE;
678
+ }
679
+ }
680
+ }
681
+
682
+ /**
683
+ * Get plugin's logo
684
+ *
685
+ * @since 2.1
686
+ * @version 1.0
687
+ */
688
+ public function getPluginLogo() {
689
+ return POST_SMTP_ASSETS . "images/logos/wp-smtp.png";
690
+ }
691
+ }
692
  }
Postman/Postman-Configuration/PostmanRegisterConfigurationSettings.php CHANGED
@@ -1,451 +1,451 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- class PostmanSettingsRegistry {
7
-
8
- private $options;
9
-
10
- public function __construct() {
11
- $this->options = PostmanOptions::getInstance();
12
- }
13
-
14
- /**
15
- * Fires on the admin_init method
16
- */
17
- public function on_admin_init() {
18
- $this->registerSettings();
19
- }
20
-
21
- /**
22
- * Register and add settings
23
- */
24
- private function registerSettings() {
25
-
26
- // only administrators should be able to trigger this
27
- if ( PostmanUtils::isAdmin() ) {
28
- $sanitizer = new PostmanInputSanitizer();
29
- register_setting( PostmanAdminController::SETTINGS_GROUP_NAME, PostmanOptions::POSTMAN_OPTIONS, array(
30
- $sanitizer,
31
- 'sanitize',
32
- ) );
33
-
34
- // Sanitize
35
- add_settings_section( 'transport_section', __( 'Transport', 'post-smtp' ), array(
36
- $this,
37
- 'printTransportSectionInfo',
38
- ), 'transport_options' );
39
-
40
- add_settings_field( PostmanOptions::TRANSPORT_TYPE, _x( 'Type', '(i.e.) What kind is it?', 'post-smtp' ), array(
41
- $this,
42
- 'transport_type_callback',
43
- ), 'transport_options', 'transport_section' );
44
-
45
- add_settings_field( 'smtp_mailers', __( 'Mailer Type', 'post-smtp' ), array(
46
- $this,
47
- 'smtp_mailer_callback',
48
- ), 'transport_options', 'transport_section' );
49
-
50
- // the Message From section
51
- add_settings_section( PostmanAdminController::MESSAGE_FROM_SECTION, _x( 'From Address', 'The Message Sender Email Address', 'post-smtp' ), array(
52
- $this,
53
- 'printMessageFromSectionInfo',
54
- ), PostmanAdminController::MESSAGE_FROM_OPTIONS );
55
-
56
- add_settings_field( PostmanOptions::MESSAGE_SENDER_EMAIL, __( 'Email Address', 'post-smtp' ), array(
57
- $this,
58
- 'from_email_callback',
59
- ), PostmanAdminController::MESSAGE_FROM_OPTIONS, PostmanAdminController::MESSAGE_FROM_SECTION );
60
-
61
- add_settings_field( PostmanOptions::PREVENT_MESSAGE_SENDER_EMAIL_OVERRIDE, '', array(
62
- $this,
63
- 'prevent_from_email_override_callback',
64
- ), PostmanAdminController::MESSAGE_FROM_OPTIONS, PostmanAdminController::MESSAGE_FROM_SECTION );
65
-
66
- add_settings_field( PostmanOptions::MESSAGE_SENDER_NAME, __( 'Name', 'post-smtp' ), array(
67
- $this,
68
- 'sender_name_callback',
69
- ), PostmanAdminController::MESSAGE_FROM_OPTIONS, PostmanAdminController::MESSAGE_FROM_SECTION );
70
-
71
- add_settings_field( PostmanOptions::PREVENT_MESSAGE_SENDER_NAME_OVERRIDE, '', array(
72
- $this,
73
- 'prevent_from_name_override_callback',
74
- ), PostmanAdminController::MESSAGE_FROM_OPTIONS, PostmanAdminController::MESSAGE_FROM_SECTION );
75
-
76
- // the Additional Addresses section
77
- add_settings_section( PostmanAdminController::MESSAGE_SECTION, __( 'Additional Email Addresses', 'post-smtp' ), array(
78
- $this,
79
- 'printMessageSectionInfo',
80
- ), PostmanAdminController::MESSAGE_OPTIONS );
81
-
82
- add_settings_field( PostmanOptions::REPLY_TO, __( 'Reply-To', 'post-smtp' ), array(
83
- $this,
84
- 'reply_to_callback',
85
- ), PostmanAdminController::MESSAGE_OPTIONS, PostmanAdminController::MESSAGE_SECTION );
86
-
87
- add_settings_field( PostmanOptions::FORCED_TO_RECIPIENTS, __( 'To Recipient(s)', 'post-smtp' ), array(
88
- $this,
89
- 'to_callback',
90
- ), PostmanAdminController::MESSAGE_OPTIONS, PostmanAdminController::MESSAGE_SECTION );
91
-
92
- add_settings_field( PostmanOptions::FORCED_CC_RECIPIENTS, __( 'Carbon Copy Recipient(s)', 'post-smtp' ), array(
93
- $this,
94
- 'cc_callback',
95
- ), PostmanAdminController::MESSAGE_OPTIONS, PostmanAdminController::MESSAGE_SECTION );
96
-
97
- add_settings_field( PostmanOptions::FORCED_BCC_RECIPIENTS, __( 'Blind Carbon Copy Recipient(s)', 'post-smtp' ), array(
98
- $this,
99
- 'bcc_callback',
100
- ), PostmanAdminController::MESSAGE_OPTIONS, PostmanAdminController::MESSAGE_SECTION );
101
-
102
- // the Additional Headers section
103
- add_settings_section( PostmanAdminController::MESSAGE_HEADERS_SECTION, __( 'Additional Headers', 'post-smtp' ), array(
104
- $this,
105
- 'printAdditionalHeadersSectionInfo',
106
- ), PostmanAdminController::MESSAGE_HEADERS_OPTIONS );
107
-
108
- add_settings_field( PostmanOptions::ADDITIONAL_HEADERS, __( 'Custom Headers', 'post-smtp' ), array(
109
- $this,
110
- 'headers_callback',
111
- ), PostmanAdminController::MESSAGE_HEADERS_OPTIONS, PostmanAdminController::MESSAGE_HEADERS_SECTION );
112
-
113
- // Fallback
114
-
115
- // the Email Validation section
116
- add_settings_section( PostmanAdminController::EMAIL_VALIDATION_SECTION, __( 'Validation', 'post-smtp' ), array(
117
- $this,
118
- 'printEmailValidationSectionInfo',
119
- ), PostmanAdminController::EMAIL_VALIDATION_OPTIONS );
120
-
121
- add_settings_field( PostmanOptions::ENVELOPE_SENDER, __( 'Email Address', 'post-smtp' ), array(
122
- $this,
123
- 'disable_email_validation_callback',
124
- ), PostmanAdminController::EMAIL_VALIDATION_OPTIONS, PostmanAdminController::EMAIL_VALIDATION_SECTION );
125
-
126
- // the Logging section
127
- add_settings_section( PostmanAdminController::LOGGING_SECTION, __( 'Email Log Settings', 'post-smtp' ), array(
128
- $this,
129
- 'printLoggingSectionInfo',
130
- ), PostmanAdminController::LOGGING_OPTIONS );
131
-
132
- add_settings_field( 'logging_status', __( 'Enable Logging', 'post-smtp' ), array(
133
- $this,
134
- 'loggingStatusInputField',
135
- ), PostmanAdminController::LOGGING_OPTIONS, PostmanAdminController::LOGGING_SECTION );
136
-
137
- add_settings_field( 'logging_max_entries', __( 'Maximum Log Entries', 'post-smtp' ), array(
138
- $this,
139
- 'loggingMaxEntriesInputField',
140
- ), PostmanAdminController::LOGGING_OPTIONS, PostmanAdminController::LOGGING_SECTION );
141
-
142
- add_settings_field( PostmanOptions::TRANSCRIPT_SIZE, __( 'Maximum Transcript Size', 'post-smtp' ), array(
143
- $this,
144
- 'transcriptSizeInputField',
145
- ), PostmanAdminController::LOGGING_OPTIONS, PostmanAdminController::LOGGING_SECTION );
146
-
147
- // the Network section
148
- add_settings_section( PostmanAdminController::NETWORK_SECTION, __( 'Network Settings', 'post-smtp' ), array(
149
- $this,
150
- 'printNetworkSectionInfo',
151
- ), PostmanAdminController::NETWORK_OPTIONS );
152
-
153
- add_settings_field( 'connection_timeout', _x( 'TCP Connection Timeout (sec)', 'Configuration Input Field', 'post-smtp' ), array(
154
- $this,
155
- 'connection_timeout_callback',
156
- ), PostmanAdminController::NETWORK_OPTIONS, PostmanAdminController::NETWORK_SECTION );
157
-
158
- add_settings_field( 'read_timeout', _x( 'TCP Read Timeout (sec)', 'Configuration Input Field', 'post-smtp' ), array(
159
- $this,
160
- 'read_timeout_callback',
161
- ), PostmanAdminController::NETWORK_OPTIONS, PostmanAdminController::NETWORK_SECTION );
162
-
163
- // the Advanced section
164
- add_settings_section( PostmanAdminController::ADVANCED_SECTION, _x( 'Miscellaneous Settings', 'Configuration Section Title', 'post-smtp' ), array(
165
- $this,
166
- 'printAdvancedSectionInfo',
167
- ), PostmanAdminController::ADVANCED_OPTIONS );
168
-
169
- add_settings_field( PostmanOptions::LOG_LEVEL, _x( 'PHP Log Level', 'Configuration Input Field', 'post-smtp' ), array(
170
- $this,
171
- 'log_level_callback',
172
- ), PostmanAdminController::ADVANCED_OPTIONS, PostmanAdminController::ADVANCED_SECTION );
173
-
174
- add_settings_field( PostmanOptions::RUN_MODE, _x( 'Delivery Mode', 'Configuration Input Field', 'post-smtp' ), array(
175
- $this,
176
- 'runModeCallback',
177
- ), PostmanAdminController::ADVANCED_OPTIONS, PostmanAdminController::ADVANCED_SECTION );
178
-
179
- add_settings_field( PostmanOptions::STEALTH_MODE, _x( 'Stealth Mode', 'This mode removes the Postman X-Mailer signature from emails', 'post-smtp' ), array(
180
- $this,
181
- 'stealthModeCallback',
182
- ), PostmanAdminController::ADVANCED_OPTIONS, PostmanAdminController::ADVANCED_SECTION );
183
-
184
- add_settings_field( PostmanOptions::TEMPORARY_DIRECTORY, __( 'Temporary Directory', 'post-smtp' ), array(
185
- $this,
186
- 'temporaryDirectoryCallback',
187
- ), PostmanAdminController::ADVANCED_OPTIONS, PostmanAdminController::ADVANCED_SECTION );
188
-
189
- do_action( 'post_smtp_settings_fields' );
190
- }
191
- }
192
-
193
- /**
194
- * Print the Transport section info
195
- */
196
- public function printTransportSectionInfo() {
197
- print __( 'Choose SMTP or a vendor-specific API:', 'post-smtp' );
198
- }
199
- public function printLoggingSectionInfo() {
200
- print __( 'Configure the delivery audit log:', 'post-smtp' );
201
- }
202
-
203
- /**
204
- * Print the Section text
205
- */
206
- public function printMessageFromSectionInfo() {
207
- print sprintf( __( 'This address, like the <b>letterhead</b> printed on a letter, identifies the sender to the recipient. Change this when you are sending on behalf of someone else, for example to use Google\'s <a href="%s">Send Mail As</a> feature. Other plugins, especially Contact Forms, may override this field to be your visitor\'s address.', 'post-smtp' ), 'https://support.google.com/mail/answer/22370?hl=en' );
208
- }
209
-
210
- /**
211
- * Print the Section text
212
- */
213
- public function printMessageSectionInfo() {
214
- print __( 'Separate multiple <b>to</b>/<b>cc</b>/<b>bcc</b> recipients with commas.', 'post-smtp' );
215
- }
216
-
217
- /**
218
- * Print the Section text
219
- */
220
- public function printNetworkSectionInfo() {
221
- print __( 'Increase the timeouts if your host is intermittenly failing to send mail. Be careful, this also correlates to how long your user must wait if the mail server is unreachable.', 'post-smtp' );
222
- }
223
-
224
- /**
225
- * Print the Section text
226
- */
227
- public function printAdvancedSectionInfo() {
228
- }
229
-
230
- /**
231
- * Print the Section text
232
- */
233
- public function printNotificationsSectionInfo() {
234
- }
235
-
236
- /**
237
- * Print the Section text
238
- */
239
- public function printAdditionalHeadersSectionInfo() {
240
- print __( 'Specify custom headers (e.g. <code>X-MC-Tags: wordpress-site-A</code>), one per line. Use custom headers with caution as they can negatively affect your Spam score.', 'post-smtp' );
241
- }
242
-
243
- /**
244
- * Print the Email Validation Description
245
- */
246
- public function printEmailValidationSectionInfo() {
247
- print __( 'E-mail addresses can be validated before sending e-mail, however this may fail with some newer domains.', 'post-smtp' );
248
- }
249
-
250
- /**
251
- * Get the settings option array and print one of its values
252
- */
253
- public function transport_type_callback() {
254
- $transportType = $this->options->getTransportType();
255
- printf( '<select id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]">', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::TRANSPORT_TYPE );
256
- foreach ( PostmanTransportRegistry::getInstance()->getTransports() as $transport ) {
257
- printf( '<option class="input_tx_type_%1$s" value="%1$s" %3$s>%2$s</option>', $transport->getSlug(), $transport->getName(), $transportType == $transport->getSlug() ? 'selected="selected"' : '' );
258
- }
259
- print '</select>';
260
- }
261
-
262
- /**
263
- * Get the settings option array and print one of its values
264
- */
265
- public function smtp_mailer_callback() {
266
- $smtp_mailers = PostmanOptions::SMTP_MAILERS;
267
- $current_smtp_mailer = $this->options->getSmtpMailer();
268
- printf( '<select id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]">', PostmanOptions::POSTMAN_OPTIONS, 'smtp_mailers' );
269
- foreach ( $smtp_mailers as $key => $smtp_mailer ) {
270
- printf( '<option class="input_tx_type_%1$s" value="%1$s" %3$s>%2$s</option>', $key, $smtp_mailer, $current_smtp_mailer == $key ? 'selected="selected"' : '' );
271
- }
272
- print '</select>';
273
- ?>
274
- <p class="description" id="mailer-type-description"><?php _e( 'Beta Feature: ONLY change this to <strong>PHPMailer</strong> only if you see <code>wp_mail</code> conflict message, conflicts when another plugin is activated, and <strong><u>sometimes</u></strong> your mail marked as spam.', 'post-smtp' ); ?></p>
275
- <?php
276
- }
277
-
278
- /**
279
- * Get the settings option array and print one of its values
280
- */
281
- public function sender_name_callback() {
282
- printf( '<input type="text" id="input_sender_name" class="ps-input ps-w-75" name="postman_options[sender_name]" value="%s" size="40" />', null !== $this->options->getMessageSenderName() ? esc_attr( $this->options->getMessageSenderName() ) : '' );
283
- }
284
-
285
- /**
286
- */
287
- public function prevent_from_name_override_callback() {
288
- $enforced = $this->options->isPluginSenderNameEnforced();
289
- printf( '<input type="checkbox" id="input_prevent_sender_name_override" name="postman_options[prevent_sender_name_override]" %s /> %s', $enforced ? 'checked="checked"' : '', __( 'Prevent <b>plugins</b> and <b>themes</b> from changing this', 'post-smtp' ) );
290
- }
291
-
292
- /**
293
- * Get the settings option array and print one of its values
294
- */
295
- public function from_email_callback() {
296
- printf( '<input type="email" id="input_sender_email" class="ps-input ps-w-75" name="postman_options[sender_email]" value="%s" size="40" class="required" placeholder="%s"/>', null !== $this->options->getMessageSenderEmail() ? esc_attr( $this->options->getMessageSenderEmail() ) : '', __( 'Required', 'post-smtp' ) );
297
- }
298
-
299
- /**
300
- * Print the Section text
301
- */
302
- public function printMessageSenderSectionInfo() {
303
- print sprintf( __( 'This address, like the <b>return address</b> printed on an envelope, identifies the account owner to the SMTP server.', 'post-smtp' ), 'https://support.google.com/mail/answer/22370?hl=en' );
304
- }
305
-
306
- /**
307
- * Get the settings option array and print one of its values
308
- */
309
- public function prevent_from_email_override_callback() {
310
- $enforced = $this->options->isPluginSenderEmailEnforced();
311
- printf( '<input type="checkbox" id="input_prevent_sender_email_override" name="postman_options[prevent_sender_email_override]" %s /> %s', $enforced ? 'checked="checked"' : '', __( 'Prevent <b>plugins</b> and <b>themes</b> from changing this', 'post-smtp' ) );
312
- }
313
-
314
- /**
315
- * Shows the Mail Logging enable/disabled option
316
- */
317
- public function loggingStatusInputField() {
318
- // isMailLoggingAllowed
319
- $disabled = '';
320
- if ( ! $this->options->isMailLoggingAllowed() ) {
321
- $disabled = 'disabled="disabled" ';
322
- }
323
- printf( '<select ' . $disabled . 'id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]">', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::MAIL_LOG_ENABLED_OPTION );
324
- printf( '<option value="%s" %s>%s</option>', PostmanOptions::MAIL_LOG_ENABLED_OPTION_YES, $this->options->isMailLoggingEnabled() ? 'selected="selected"' : '', __( 'Yes', 'post-smtp' ) );
325
- printf( '<option value="%s" %s>%s</option>', PostmanOptions::MAIL_LOG_ENABLED_OPTION_NO, ! $this->options->isMailLoggingEnabled() ? 'selected="selected"' : '', __( 'No', 'post-smtp' ) );
326
- printf( '</select>' );
327
- }
328
- public function loggingMaxEntriesInputField() {
329
- printf( '<input type="text" id="input_logging_max_entries" name="postman_options[%s]" value="%s"/>', PostmanOptions::MAIL_LOG_MAX_ENTRIES, $this->options->getMailLoggingMaxEntries() );
330
- }
331
- public function transcriptSizeInputField() {
332
- $inputOptionsSlug = PostmanOptions::POSTMAN_OPTIONS;
333
- $inputTranscriptSlug = PostmanOptions::TRANSCRIPT_SIZE;
334
- $inputValue = $this->options->getTranscriptSize();
335
- $inputDescription = __( 'Change this value if you can\'t see the beginning of the transcript because your messages are too big.', 'post-smtp' );
336
- printf( '<input type="text" id="input%2$s" name="%1$s[%2$s]" value="%3$s"/><br/><span class="postman_input_description">%4$s</span>', $inputOptionsSlug, $inputTranscriptSlug, $inputValue, $inputDescription );
337
- }
338
-
339
- /**
340
- * Get the settings option array and print one of its values
341
- */
342
- public function reply_to_callback() {
343
- printf( '<input type="text" id="input_reply_to" name="%s[%s]" value="%s" size="40" />', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::REPLY_TO, null !== $this->options->getReplyTo() ? esc_attr( $this->options->getReplyTo() ) : '' );
344
- }
345
-
346
- /**
347
- * Get the settings option array and print one of its values
348
- */
349
- public function to_callback() {
350
- printf( '<input type="text" id="input_to" name="%s[%s]" value="%s" size="60" />', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::FORCED_TO_RECIPIENTS, null !== $this->options->getForcedToRecipients() ? esc_attr( $this->options->getForcedToRecipients() ) : '' );
351
- }
352
-
353
- /**
354
- * Get the settings option array and print one of its values
355
- */
356
- public function cc_callback() {
357
- printf( '<input type="text" id="input_cc" name="%s[%s]" value="%s" size="60" />', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::FORCED_CC_RECIPIENTS, null !== $this->options->getForcedCcRecipients() ? esc_attr( $this->options->getForcedCcRecipients() ) : '' );
358
- }
359
-
360
- /**
361
- * Get the settings option array and print one of its values
362
- */
363
- public function bcc_callback() {
364
- printf( '<input type="text" id="input_bcc" name="%s[%s]" value="%s" size="60" />', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::FORCED_BCC_RECIPIENTS, null !== $this->options->getForcedBccRecipients() ? esc_attr( $this->options->getForcedBccRecipients() ) : '' );
365
- }
366
-
367
- /**
368
- * Get the settings option array and print one of its values
369
- */
370
- public function headers_callback() {
371
- printf( '<textarea id="input_headers" name="%s[%s]" cols="60" rows="5" >%s</textarea>', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::ADDITIONAL_HEADERS, null !== $this->options->getAdditionalHeaders() ? esc_attr( $this->options->getAdditionalHeaders() ) : '' );
372
- }
373
-
374
- /**
375
- */
376
- public function disable_email_validation_callback() {
377
- $disabled = $this->options->isEmailValidationDisabled();
378
- printf( '<input type="checkbox" id="%2$s" name="%1$s[%2$s]" %3$s /> %4$s', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::DISABLE_EMAIL_VALIDAITON, $disabled ? 'checked="checked"' : '', __( 'Disable e-mail validation', 'post-smtp' ) );
379
- }
380
-
381
- /**
382
- * Get the settings option array and print one of its values
383
- */
384
- public function log_level_callback() {
385
- $inputDescription = sprintf( __( 'Log Level specifies the level of detail written to the <a target="_blank" href="%s">WordPress Debug log</a> - view the log with <a target-"_new" href="%s">Debug</a>.', 'post-smtp' ), 'https://codex.wordpress.org/Debugging_in_WordPress', 'https://wordpress.org/plugins/debug/' );
386
- printf( '<select id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]">', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::LOG_LEVEL );
387
- $currentKey = $this->options->getLogLevel();
388
- $this->printSelectOption( __( 'Off', 'post-smtp' ), PostmanLogger::OFF_INT, $currentKey );
389
- $this->printSelectOption( __( 'Trace', 'post-smtp' ), PostmanLogger::TRACE_INT, $currentKey );
390
- $this->printSelectOption( __( 'Debug', 'post-smtp' ), PostmanLogger::DEBUG_INT, $currentKey );
391
- $this->printSelectOption( __( 'Info', 'post-smtp' ), PostmanLogger::INFO_INT, $currentKey );
392
- $this->printSelectOption( __( 'Warning', 'post-smtp' ), PostmanLogger::WARN_INT, $currentKey );
393
- $this->printSelectOption( __( 'Error', 'post-smtp' ), PostmanLogger::ERROR_INT, $currentKey );
394
- printf( '</select><br/><span class="postman_input_description">%s</span>', $inputDescription );
395
- }
396
-
397
- private function printSelectOption( $label, $optionKey, $currentKey ) {
398
- $optionPattern = '<option value="%1$s" %2$s>%3$s</option>';
399
- printf( $optionPattern, $optionKey, $optionKey == $currentKey ? 'selected="selected"' : '', $label );
400
- }
401
- public function runModeCallback() {
402
- $inputDescription = __( 'Delivery mode offers options useful for developing or testing.', 'post-smtp' );
403
- printf( '<select id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]">', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::RUN_MODE );
404
- $currentKey = $this->options->getRunMode();
405
- $this->printSelectOption( _x( 'Log Email and Send', 'When the server is online to the public, this is "Production" mode', 'post-smtp' ), PostmanOptions::RUN_MODE_PRODUCTION, $currentKey );
406
- $this->printSelectOption( __( 'Log Email and Delete', 'post-smtp' ), PostmanOptions::RUN_MODE_LOG_ONLY, $currentKey );
407
- $this->printSelectOption( __( 'Delete All Emails', 'post-smtp' ), PostmanOptions::RUN_MODE_IGNORE, $currentKey );
408
- printf( '</select><br/><span class="postman_input_description">%s</span>', $inputDescription );
409
- }
410
-
411
- public function stealthModeCallback() {
412
- printf( '<input type="checkbox" id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]" %3$s /> %4$s', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::STEALTH_MODE, $this->options->isStealthModeEnabled() ? 'checked="checked"' : '', __( 'Remove the Postman X-Header signature from messages', 'post-smtp' ) );
413
- }
414
-
415
- public function temporaryDirectoryCallback() {
416
- $inputDescription = __( 'Lockfiles are written here to prevent users from triggering an OAuth 2.0 token refresh at the same time.' );
417
- printf(
418
- '<input type="text" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />',
419
- PostmanOptions::POSTMAN_OPTIONS,
420
- PostmanOptions::TEMPORARY_DIRECTORY,
421
- esc_attr( $this->options->getTempDirectory() )
422
- );
423
-
424
- if ( PostmanState::getInstance()->isFileLockingEnabled() ) {
425
- printf( ' <span style="color:green">%s</span></br><span class="postman_input_description">%s</span>', __( 'Valid', 'post-smtp' ), $inputDescription );
426
- } else {
427
- printf( ' <span style="color:red">%s</span></br><span class="postman_input_description">%s</span>', __( 'Invalid', 'post-smtp' ), $inputDescription );
428
- }
429
- }
430
-
431
- /**
432
- * Get the settings option array and print one of its values
433
- */
434
- public function connection_timeout_callback() {
435
- printf( '<input type="text" id="input_connection_timeout" name="%s[%s]" value="%s" />', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::CONNECTION_TIMEOUT, $this->options->getConnectionTimeout() );
436
- }
437
-
438
- /**
439
- * Get the settings option array and print one of its values
440
- */
441
- public function read_timeout_callback() {
442
- printf( '<input type="text" id="input_read_timeout" name="%s[%s]" value="%s" />', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::READ_TIMEOUT, $this->options->getReadTimeout() );
443
- }
444
-
445
- /**
446
- * Get the settings option array and print one of its values
447
- */
448
- public function port_callback( $args ) {
449
- printf( '<input type="text" id="input_port" name="postman_options[port]" value="%s" %s placeholder="%s"/>', null !== $this->options->getPort() ? esc_attr( $this->options->getPort() ) : '', isset( $args ['style'] ) ? $args ['style'] : '', __( 'Required', 'post-smtp' ) );
450
- }
451
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ class PostmanSettingsRegistry {
7
+
8
+ private $options;
9
+
10
+ public function __construct() {
11
+ $this->options = PostmanOptions::getInstance();
12
+ }
13
+
14
+ /**
15
+ * Fires on the admin_init method
16
+ */
17
+ public function on_admin_init() {
18
+ $this->registerSettings();
19
+ }
20
+
21
+ /**
22
+ * Register and add settings
23
+ */
24
+ private function registerSettings() {
25
+
26
+ // only administrators should be able to trigger this
27
+ if ( PostmanUtils::isAdmin() ) {
28
+ $sanitizer = new PostmanInputSanitizer();
29
+ register_setting( PostmanAdminController::SETTINGS_GROUP_NAME, PostmanOptions::POSTMAN_OPTIONS, array(
30
+ $sanitizer,
31
+ 'sanitize',
32
+ ) );
33
+
34
+ // Sanitize
35
+ add_settings_section( 'transport_section', __( 'Transport', 'post-smtp' ), array(
36
+ $this,
37
+ 'printTransportSectionInfo',
38
+ ), 'transport_options' );
39
+
40
+ add_settings_field( PostmanOptions::TRANSPORT_TYPE, _x( 'Type', '(i.e.) What kind is it?', 'post-smtp' ), array(
41
+ $this,
42
+ 'transport_type_callback',
43
+ ), 'transport_options', 'transport_section' );
44
+
45
+ add_settings_field( 'smtp_mailers', __( 'Mailer Type', 'post-smtp' ), array(
46
+ $this,
47
+ 'smtp_mailer_callback',
48
+ ), 'transport_options', 'transport_section' );
49
+
50
+ // the Message From section
51
+ add_settings_section( PostmanAdminController::MESSAGE_FROM_SECTION, _x( 'From Address', 'The Message Sender Email Address', 'post-smtp' ), array(
52
+ $this,
53
+ 'printMessageFromSectionInfo',
54
+ ), PostmanAdminController::MESSAGE_FROM_OPTIONS );
55
+
56
+ add_settings_field( PostmanOptions::MESSAGE_SENDER_EMAIL, __( 'Email Address', 'post-smtp' ), array(
57
+ $this,
58
+ 'from_email_callback',
59
+ ), PostmanAdminController::MESSAGE_FROM_OPTIONS, PostmanAdminController::MESSAGE_FROM_SECTION );
60
+
61
+ add_settings_field( PostmanOptions::PREVENT_MESSAGE_SENDER_EMAIL_OVERRIDE, '', array(
62
+ $this,
63
+ 'prevent_from_email_override_callback',
64
+ ), PostmanAdminController::MESSAGE_FROM_OPTIONS, PostmanAdminController::MESSAGE_FROM_SECTION );
65
+
66
+ add_settings_field( PostmanOptions::MESSAGE_SENDER_NAME, __( 'Name', 'post-smtp' ), array(
67
+ $this,
68
+ 'sender_name_callback',
69
+ ), PostmanAdminController::MESSAGE_FROM_OPTIONS, PostmanAdminController::MESSAGE_FROM_SECTION );
70
+
71
+ add_settings_field( PostmanOptions::PREVENT_MESSAGE_SENDER_NAME_OVERRIDE, '', array(
72
+ $this,
73
+ 'prevent_from_name_override_callback',
74
+ ), PostmanAdminController::MESSAGE_FROM_OPTIONS, PostmanAdminController::MESSAGE_FROM_SECTION );
75
+
76
+ // the Additional Addresses section
77
+ add_settings_section( PostmanAdminController::MESSAGE_SECTION, __( 'Additional Email Addresses', 'post-smtp' ), array(
78
+ $this,
79
+ 'printMessageSectionInfo',
80
+ ), PostmanAdminController::MESSAGE_OPTIONS );
81
+
82
+ add_settings_field( PostmanOptions::REPLY_TO, __( 'Reply-To', 'post-smtp' ), array(
83
+ $this,
84
+ 'reply_to_callback',
85
+ ), PostmanAdminController::MESSAGE_OPTIONS, PostmanAdminController::MESSAGE_SECTION );
86
+
87
+ add_settings_field( PostmanOptions::FORCED_TO_RECIPIENTS, __( 'To Recipient(s)', 'post-smtp' ), array(
88
+ $this,
89
+ 'to_callback',
90
+ ), PostmanAdminController::MESSAGE_OPTIONS, PostmanAdminController::MESSAGE_SECTION );
91
+
92
+ add_settings_field( PostmanOptions::FORCED_CC_RECIPIENTS, __( 'Carbon Copy Recipient(s)', 'post-smtp' ), array(
93
+ $this,
94
+ 'cc_callback',
95
+ ), PostmanAdminController::MESSAGE_OPTIONS, PostmanAdminController::MESSAGE_SECTION );
96
+
97
+ add_settings_field( PostmanOptions::FORCED_BCC_RECIPIENTS, __( 'Blind Carbon Copy Recipient(s)', 'post-smtp' ), array(
98
+ $this,
99
+ 'bcc_callback',
100
+ ), PostmanAdminController::MESSAGE_OPTIONS, PostmanAdminController::MESSAGE_SECTION );
101
+
102
+ // the Additional Headers section
103
+ add_settings_section( PostmanAdminController::MESSAGE_HEADERS_SECTION, __( 'Additional Headers', 'post-smtp' ), array(
104
+ $this,
105
+ 'printAdditionalHeadersSectionInfo',
106
+ ), PostmanAdminController::MESSAGE_HEADERS_OPTIONS );
107
+
108
+ add_settings_field( PostmanOptions::ADDITIONAL_HEADERS, __( 'Custom Headers', 'post-smtp' ), array(
109
+ $this,
110
+ 'headers_callback',
111
+ ), PostmanAdminController::MESSAGE_HEADERS_OPTIONS, PostmanAdminController::MESSAGE_HEADERS_SECTION );
112
+
113
+ // Fallback
114
+
115
+ // the Email Validation section
116
+ add_settings_section( PostmanAdminController::EMAIL_VALIDATION_SECTION, __( 'Validation', 'post-smtp' ), array(
117
+ $this,
118
+ 'printEmailValidationSectionInfo',
119
+ ), PostmanAdminController::EMAIL_VALIDATION_OPTIONS );
120
+
121
+ add_settings_field( PostmanOptions::ENVELOPE_SENDER, __( 'Email Address', 'post-smtp' ), array(
122
+ $this,
123
+ 'disable_email_validation_callback',
124
+ ), PostmanAdminController::EMAIL_VALIDATION_OPTIONS, PostmanAdminController::EMAIL_VALIDATION_SECTION );
125
+
126
+ // the Logging section
127
+ add_settings_section( PostmanAdminController::LOGGING_SECTION, __( 'Email Log Settings', 'post-smtp' ), array(
128
+ $this,
129
+ 'printLoggingSectionInfo',
130
+ ), PostmanAdminController::LOGGING_OPTIONS );
131
+
132
+ add_settings_field( 'logging_status', __( 'Enable Logging', 'post-smtp' ), array(
133
+ $this,
134
+ 'loggingStatusInputField',
135
+ ), PostmanAdminController::LOGGING_OPTIONS, PostmanAdminController::LOGGING_SECTION );
136
+
137
+ add_settings_field( 'logging_max_entries', __( 'Maximum Log Entries', 'post-smtp' ), array(
138
+ $this,
139
+ 'loggingMaxEntriesInputField',
140
+ ), PostmanAdminController::LOGGING_OPTIONS, PostmanAdminController::LOGGING_SECTION );
141
+
142
+ add_settings_field( PostmanOptions::TRANSCRIPT_SIZE, __( 'Maximum Transcript Size', 'post-smtp' ), array(
143
+ $this,
144
+ 'transcriptSizeInputField',
145
+ ), PostmanAdminController::LOGGING_OPTIONS, PostmanAdminController::LOGGING_SECTION );
146
+
147
+ // the Network section
148
+ add_settings_section( PostmanAdminController::NETWORK_SECTION, __( 'Network Settings', 'post-smtp' ), array(
149
+ $this,
150
+ 'printNetworkSectionInfo',
151
+ ), PostmanAdminController::NETWORK_OPTIONS );
152
+
153
+ add_settings_field( 'connection_timeout', _x( 'TCP Connection Timeout (sec)', 'Configuration Input Field', 'post-smtp' ), array(
154
+ $this,
155
+ 'connection_timeout_callback',
156
+ ), PostmanAdminController::NETWORK_OPTIONS, PostmanAdminController::NETWORK_SECTION );
157
+
158
+ add_settings_field( 'read_timeout', _x( 'TCP Read Timeout (sec)', 'Configuration Input Field', 'post-smtp' ), array(
159
+ $this,
160
+ 'read_timeout_callback',
161
+ ), PostmanAdminController::NETWORK_OPTIONS, PostmanAdminController::NETWORK_SECTION );
162
+
163
+ // the Advanced section
164
+ add_settings_section( PostmanAdminController::ADVANCED_SECTION, _x( 'Miscellaneous Settings', 'Configuration Section Title', 'post-smtp' ), array(
165
+ $this,
166
+ 'printAdvancedSectionInfo',
167
+ ), PostmanAdminController::ADVANCED_OPTIONS );
168
+
169
+ add_settings_field( PostmanOptions::LOG_LEVEL, _x( 'PHP Log Level', 'Configuration Input Field', 'post-smtp' ), array(
170
+ $this,
171
+ 'log_level_callback',
172
+ ), PostmanAdminController::ADVANCED_OPTIONS, PostmanAdminController::ADVANCED_SECTION );
173
+
174
+ add_settings_field( PostmanOptions::RUN_MODE, _x( 'Delivery Mode', 'Configuration Input Field', 'post-smtp' ), array(
175
+ $this,
176
+ 'runModeCallback',
177
+ ), PostmanAdminController::ADVANCED_OPTIONS, PostmanAdminController::ADVANCED_SECTION );
178
+
179
+ add_settings_field( PostmanOptions::STEALTH_MODE, _x( 'Stealth Mode', 'This mode removes the Postman X-Mailer signature from emails', 'post-smtp' ), array(
180
+ $this,
181
+ 'stealthModeCallback',
182
+ ), PostmanAdminController::ADVANCED_OPTIONS, PostmanAdminController::ADVANCED_SECTION );
183
+
184
+ add_settings_field( PostmanOptions::TEMPORARY_DIRECTORY, __( 'Temporary Directory', 'post-smtp' ), array(
185
+ $this,
186
+ 'temporaryDirectoryCallback',
187
+ ), PostmanAdminController::ADVANCED_OPTIONS, PostmanAdminController::ADVANCED_SECTION );
188
+
189
+ do_action( 'post_smtp_settings_fields' );
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Print the Transport section info
195
+ */
196
+ public function printTransportSectionInfo() {
197
+ print __( 'Choose SMTP or a vendor-specific API:', 'post-smtp' );
198
+ }
199
+ public function printLoggingSectionInfo() {
200
+ print __( 'Configure the delivery audit log:', 'post-smtp' );
201
+ }
202
+
203
+ /**
204
+ * Print the Section text
205
+ */
206
+ public function printMessageFromSectionInfo() {
207
+ print sprintf( __( 'This address, like the <b>letterhead</b> printed on a letter, identifies the sender to the recipient. Change this when you are sending on behalf of someone else, for example to use Google\'s <a href="%s">Send Mail As</a> feature. Other plugins, especially Contact Forms, may override this field to be your visitor\'s address.', 'post-smtp' ), 'https://support.google.com/mail/answer/22370?hl=en' );
208
+ }
209
+
210
+ /**
211
+ * Print the Section text
212
+ */
213
+ public function printMessageSectionInfo() {
214
+ print __( 'Separate multiple <b>to</b>/<b>cc</b>/<b>bcc</b> recipients with commas.', 'post-smtp' );
215
+ }
216
+
217
+ /**
218
+ * Print the Section text
219
+ */
220
+ public function printNetworkSectionInfo() {
221
+ print __( 'Increase the timeouts if your host is intermittenly failing to send mail. Be careful, this also correlates to how long your user must wait if the mail server is unreachable.', 'post-smtp' );
222
+ }
223
+
224
+ /**
225
+ * Print the Section text
226
+ */
227
+ public function printAdvancedSectionInfo() {
228
+ }
229
+
230
+ /**
231
+ * Print the Section text
232
+ */
233
+ public function printNotificationsSectionInfo() {
234
+ }
235
+
236
+ /**
237
+ * Print the Section text
238
+ */
239
+ public function printAdditionalHeadersSectionInfo() {
240
+ print __( 'Specify custom headers (e.g. <code>X-MC-Tags: wordpress-site-A</code>), one per line. Use custom headers with caution as they can negatively affect your Spam score.', 'post-smtp' );
241
+ }
242
+
243
+ /**
244
+ * Print the Email Validation Description
245
+ */
246
+ public function printEmailValidationSectionInfo() {
247
+ print __( 'E-mail addresses can be validated before sending e-mail, however this may fail with some newer domains.', 'post-smtp' );
248
+ }
249
+
250
+ /**
251
+ * Get the settings option array and print one of its values
252
+ */
253
+ public function transport_type_callback() {
254
+ $transportType = $this->options->getTransportType();
255
+ printf( '<select id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]">', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::TRANSPORT_TYPE );
256
+ foreach ( PostmanTransportRegistry::getInstance()->getTransports() as $transport ) {
257
+ printf( '<option class="input_tx_type_%1$s" value="%1$s" %3$s>%2$s</option>', $transport->getSlug(), $transport->getName(), $transportType == $transport->getSlug() ? 'selected="selected"' : '' );
258
+ }
259
+ print '</select>';
260
+ }
261
+
262
+ /**
263
+ * Get the settings option array and print one of its values
264
+ */
265
+ public function smtp_mailer_callback() {
266
+ $smtp_mailers = PostmanOptions::SMTP_MAILERS;
267
+ $current_smtp_mailer = $this->options->getSmtpMailer();
268
+ printf( '<select id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]">', PostmanOptions::POSTMAN_OPTIONS, 'smtp_mailers' );
269
+ foreach ( $smtp_mailers as $key => $smtp_mailer ) {
270
+ printf( '<option class="input_tx_type_%1$s" value="%1$s" %3$s>%2$s</option>', $key, $smtp_mailer, $current_smtp_mailer == $key ? 'selected="selected"' : '' );
271
+ }
272
+ print '</select>';
273
+ ?>
274
+ <p class="description" id="mailer-type-description"><?php _e( 'Beta Feature: ONLY change this to <strong>PHPMailer</strong> only if you see <code>wp_mail</code> conflict message, conflicts when another plugin is activated, and <strong><u>sometimes</u></strong> your mail marked as spam.', 'post-smtp' ); ?></p>
275
+ <?php
276
+ }
277
+
278
+ /**
279
+ * Get the settings option array and print one of its values
280
+ */
281
+ public function sender_name_callback() {
282
+ printf( '<input type="text" id="input_sender_name" class="ps-input ps-w-75" name="postman_options[sender_name]" value="%s" size="40" />', null !== $this->options->getMessageSenderName() ? esc_attr( $this->options->getMessageSenderName() ) : '' );
283
+ }
284
+
285
+ /**
286
+ */
287
+ public function prevent_from_name_override_callback() {
288
+ $enforced = $this->options->isPluginSenderNameEnforced();
289
+ printf( '<input type="checkbox" id="input_prevent_sender_name_override" name="postman_options[prevent_sender_name_override]" %s /> %s', $enforced ? 'checked="checked"' : '', __( 'Prevent <b>plugins</b> and <b>themes</b> from changing this', 'post-smtp' ) );
290
+ }
291
+
292
+ /**
293
+ * Get the settings option array and print one of its values
294
+ */
295
+ public function from_email_callback() {
296
+ printf( '<input type="email" id="input_sender_email" class="ps-input ps-w-75" name="postman_options[sender_email]" value="%s" size="40" class="required" placeholder="%s"/>', null !== $this->options->getMessageSenderEmail() ? esc_attr( $this->options->getMessageSenderEmail() ) : '', __( 'Required', 'post-smtp' ) );
297
+ }
298
+
299
+ /**
300
+ * Print the Section text
301
+ */
302
+ public function printMessageSenderSectionInfo() {
303
+ print sprintf( __( 'This address, like the <b>return address</b> printed on an envelope, identifies the account owner to the SMTP server.', 'post-smtp' ), 'https://support.google.com/mail/answer/22370?hl=en' );
304
+ }
305
+
306
+ /**
307
+ * Get the settings option array and print one of its values
308
+ */
309
+ public function prevent_from_email_override_callback() {
310
+ $enforced = $this->options->isPluginSenderEmailEnforced();
311
+ printf( '<input type="checkbox" id="input_prevent_sender_email_override" name="postman_options[prevent_sender_email_override]" %s /> %s', $enforced ? 'checked="checked"' : '', __( 'Prevent <b>plugins</b> and <b>themes</b> from changing this', 'post-smtp' ) );
312
+ }
313
+
314
+ /**
315
+ * Shows the Mail Logging enable/disabled option
316
+ */
317
+ public function loggingStatusInputField() {
318
+ // isMailLoggingAllowed
319
+ $disabled = '';
320
+ if ( ! $this->options->isMailLoggingAllowed() ) {
321
+ $disabled = 'disabled="disabled" ';
322
+ }
323
+ printf( '<select ' . $disabled . 'id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]">', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::MAIL_LOG_ENABLED_OPTION );
324
+ printf( '<option value="%s" %s>%s</option>', PostmanOptions::MAIL_LOG_ENABLED_OPTION_YES, $this->options->isMailLoggingEnabled() ? 'selected="selected"' : '', __( 'Yes', 'post-smtp' ) );
325
+ printf( '<option value="%s" %s>%s</option>', PostmanOptions::MAIL_LOG_ENABLED_OPTION_NO, ! $this->options->isMailLoggingEnabled() ? 'selected="selected"' : '', __( 'No', 'post-smtp' ) );
326
+ printf( '</select>' );
327
+ }
328
+ public function loggingMaxEntriesInputField() {
329
+ printf( '<input type="text" id="input_logging_max_entries" name="postman_options[%s]" value="%s"/>', PostmanOptions::MAIL_LOG_MAX_ENTRIES, $this->options->getMailLoggingMaxEntries() );
330
+ }
331
+ public function transcriptSizeInputField() {
332
+ $inputOptionsSlug = PostmanOptions::POSTMAN_OPTIONS;
333
+ $inputTranscriptSlug = PostmanOptions::TRANSCRIPT_SIZE;
334
+ $inputValue = $this->options->getTranscriptSize();
335
+ $inputDescription = __( 'Change this value if you can\'t see the beginning of the transcript because your messages are too big.', 'post-smtp' );
336
+ printf( '<input type="text" id="input%2$s" name="%1$s[%2$s]" value="%3$s"/><br/><span class="postman_input_description">%4$s</span>', $inputOptionsSlug, $inputTranscriptSlug, $inputValue, $inputDescription );
337
+ }
338
+
339
+ /**
340
+ * Get the settings option array and print one of its values
341
+ */
342
+ public function reply_to_callback() {
343
+ printf( '<input type="text" id="input_reply_to" name="%s[%s]" value="%s" size="40" />', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::REPLY_TO, null !== $this->options->getReplyTo() ? esc_attr( $this->options->getReplyTo() ) : '' );
344
+ }
345
+
346
+ /**
347
+ * Get the settings option array and print one of its values
348
+ */
349
+ public function to_callback() {
350
+ printf( '<input type="text" id="input_to" name="%s[%s]" value="%s" size="60" />', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::FORCED_TO_RECIPIENTS, null !== $this->options->getForcedToRecipients() ? esc_attr( $this->options->getForcedToRecipients() ) : '' );
351
+ }
352
+
353
+ /**
354
+ * Get the settings option array and print one of its values
355
+ */
356
+ public function cc_callback() {
357
+ printf( '<input type="text" id="input_cc" name="%s[%s]" value="%s" size="60" />', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::FORCED_CC_RECIPIENTS, null !== $this->options->getForcedCcRecipients() ? esc_attr( $this->options->getForcedCcRecipients() ) : '' );
358
+ }
359
+
360
+ /**
361
+ * Get the settings option array and print one of its values
362
+ */
363
+ public function bcc_callback() {
364
+ printf( '<input type="text" id="input_bcc" name="%s[%s]" value="%s" size="60" />', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::FORCED_BCC_RECIPIENTS, null !== $this->options->getForcedBccRecipients() ? esc_attr( $this->options->getForcedBccRecipients() ) : '' );
365
+ }
366
+
367
+ /**
368
+ * Get the settings option array and print one of its values
369
+ */
370
+ public function headers_callback() {
371
+ printf( '<textarea id="input_headers" name="%s[%s]" cols="60" rows="5" >%s</textarea>', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::ADDITIONAL_HEADERS, null !== $this->options->getAdditionalHeaders() ? esc_attr( $this->options->getAdditionalHeaders() ) : '' );
372
+ }
373
+
374
+ /**
375
+ */
376
+ public function disable_email_validation_callback() {
377
+ $disabled = $this->options->isEmailValidationDisabled();
378
+ printf( '<input type="checkbox" id="%2$s" name="%1$s[%2$s]" %3$s /> %4$s', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::DISABLE_EMAIL_VALIDAITON, $disabled ? 'checked="checked"' : '', __( 'Disable e-mail validation', 'post-smtp' ) );
379
+ }
380
+
381
+ /**
382
+ * Get the settings option array and print one of its values
383
+ */
384
+ public function log_level_callback() {
385
+ $inputDescription = sprintf( __( 'Log Level specifies the level of detail written to the <a target="_blank" href="%s">WordPress Debug log</a> - view the log with <a target-"_new" href="%s">Debug</a>.', 'post-smtp' ), 'https://codex.wordpress.org/Debugging_in_WordPress', 'https://wordpress.org/plugins/debug/' );
386
+ printf( '<select id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]">', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::LOG_LEVEL );
387
+ $currentKey = $this->options->getLogLevel();
388
+ $this->printSelectOption( __( 'Off', 'post-smtp' ), PostmanLogger::OFF_INT, $currentKey );
389
+ $this->printSelectOption( __( 'Trace', 'post-smtp' ), PostmanLogger::TRACE_INT, $currentKey );
390
+ $this->printSelectOption( __( 'Debug', 'post-smtp' ), PostmanLogger::DEBUG_INT, $currentKey );
391
+ $this->printSelectOption( __( 'Info', 'post-smtp' ), PostmanLogger::INFO_INT, $currentKey );
392
+ $this->printSelectOption( __( 'Warning', 'post-smtp' ), PostmanLogger::WARN_INT, $currentKey );
393
+ $this->printSelectOption( __( 'Error', 'post-smtp' ), PostmanLogger::ERROR_INT, $currentKey );
394
+ printf( '</select><br/><span class="postman_input_description">%s</span>', $inputDescription );
395
+ }
396
+
397
+ private function printSelectOption( $label, $optionKey, $currentKey ) {
398
+ $optionPattern = '<option value="%1$s" %2$s>%3$s</option>';
399
+ printf( $optionPattern, $optionKey, $optionKey == $currentKey ? 'selected="selected"' : '', $label );
400
+ }
401
+ public function runModeCallback() {
402
+ $inputDescription = __( 'Delivery mode offers options useful for developing or testing.', 'post-smtp' );
403
+ printf( '<select id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]">', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::RUN_MODE );
404
+ $currentKey = $this->options->getRunMode();
405
+ $this->printSelectOption( _x( 'Log Email and Send', 'When the server is online to the public, this is "Production" mode', 'post-smtp' ), PostmanOptions::RUN_MODE_PRODUCTION, $currentKey );
406
+ $this->printSelectOption( __( 'Log only', 'post-smtp' ), PostmanOptions::RUN_MODE_LOG_ONLY, $currentKey );
407
+ $this->printSelectOption( __( 'No Action', 'post-smtp' ), PostmanOptions::RUN_MODE_IGNORE, $currentKey );
408
+ printf( '</select><br/><span class="postman_input_description">%s</span>', $inputDescription );
409
+ }
410
+
411
+ public function stealthModeCallback() {
412
+ printf( '<input type="checkbox" id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]" %3$s /> %4$s', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::STEALTH_MODE, $this->options->isStealthModeEnabled() ? 'checked="checked"' : '', __( 'Remove the Postman X-Header signature from messages', 'post-smtp' ) );
413
+ }
414
+
415
+ public function temporaryDirectoryCallback() {
416
+ $inputDescription = __( 'Lockfiles are written here to prevent users from triggering an OAuth 2.0 token refresh at the same time.' );
417
+ printf(
418
+ '<input type="text" id="input_%2$s" name="%1$s[%2$s]" value="%3$s" />',
419
+ PostmanOptions::POSTMAN_OPTIONS,
420
+ PostmanOptions::TEMPORARY_DIRECTORY,
421
+ esc_attr( $this->options->getTempDirectory() )
422
+ );
423
+
424
+ if ( PostmanState::getInstance()->isFileLockingEnabled() ) {
425
+ printf( ' <span style="color:green">%s</span></br><span class="postman_input_description">%s</span>', __( 'Valid', 'post-smtp' ), $inputDescription );
426
+ } else {
427
+ printf( ' <span style="color:red">%s</span></br><span class="postman_input_description">%s</span>', __( 'Invalid', 'post-smtp' ), $inputDescription );
428
+ }
429
+ }
430
+
431
+ /**
432
+ * Get the settings option array and print one of its values
433
+ */
434
+ public function connection_timeout_callback() {
435
+ printf( '<input type="text" id="input_connection_timeout" name="%s[%s]" value="%s" />', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::CONNECTION_TIMEOUT, $this->options->getConnectionTimeout() );
436
+ }
437
+
438
+ /**
439
+ * Get the settings option array and print one of its values
440
+ */
441
+ public function read_timeout_callback() {
442
+ printf( '<input type="text" id="input_read_timeout" name="%s[%s]" value="%s" />', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::READ_TIMEOUT, $this->options->getReadTimeout() );
443
+ }
444
+
445
+ /**
446
+ * Get the settings option array and print one of its values
447
+ */
448
+ public function port_callback( $args ) {
449
+ printf( '<input type="text" id="input_port" name="postman_options[port]" value="%s" %s placeholder="%s"/>', null !== $this->options->getPort() ? esc_attr( $this->options->getPort() ) : '', isset( $args ['style'] ) ? $args ['style'] : '', __( 'Required', 'post-smtp' ) );
450
+ }
451
+ }
Postman/Postman-Configuration/PostmanSmtpDiscovery.php CHANGED
@@ -1,237 +1,237 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- if (! class_exists ( 'PostmanSmtpMappings' )) {
7
- class PostmanSmtpMappings {
8
- // if an email is in this domain array, it is a known smtp server (easy lookup)
9
- private static $emailDomain = array (
10
- // from http://www.serversmtp.com/en/outgoing-mail-server-hostname
11
- '1and1.com' => 'smtp.1and1.com',
12
- 'airmail.net' => 'smtp.airmail.net',
13
- 'aol.com' => 'smtp.aol.com',
14
- 'Bluewin.ch' => 'Smtpauths.bluewin.ch',
15
- 'Comcast.net' => 'Smtp.comcast.net',
16
- 'Earthlink.net' => 'Smtpauth.earthlink.net',
17
- 'gmail.com' => 'smtp.gmail.com',
18
- 'Gmx.com' => 'mail.gmx.com',
19
- 'Gmx.net' => 'mail.gmx.com',
20
- 'Gmx.us' => 'mail.gmx.com',
21
- 'hotmail.com' => 'smtp.live.com',
22
- 'icloud.com' => 'smtp.mail.me.com',
23
- 'mail.com' => 'smtp.mail.com',
24
- 'ntlworld.com' => 'smtp.ntlworld.com',
25
- 'rocketmail.com' => 'plus.smtp.mail.yahoo.com',
26
- 'rogers.com' => 'smtp.broadband.rogers.com',
27
- 'yahoo.ca' => 'smtp.mail.yahoo.ca',
28
- 'yahoo.co.id' => 'smtp.mail.yahoo.co.id',
29
- 'yahoo.co.in' => 'smtp.mail.yahoo.co.in',
30
- 'yahoo.co.kr' => 'smtp.mail.yahoo.com',
31
- 'yahoo.com' => 'smtp.mail.yahoo.com',
32
- 'yahoo.com.ar' => 'smtp.mail.yahoo.com.ar',
33
- 'yahoo.com.au' => 'smtp.mail.yahoo.com.au',
34
- 'yahoo.com.br' => 'smtp.mail.yahoo.com.br',
35
- 'yahoo.com.cn' => 'smtp.mail.yahoo.com.cn',
36
- 'yahoo.com.hk' => 'smtp.mail.yahoo.com.hk',
37
- 'yahoo.com.mx' => 'smtp.mail.yahoo.com',
38
- 'yahoo.com.my' => 'smtp.mail.yahoo.com.my',
39
- 'yahoo.com.ph' => 'smtp.mail.yahoo.com.ph',
40
- 'yahoo.com.sg' => 'smtp.mail.yahoo.com.sg',
41
- 'yahoo.com.tw' => 'smtp.mail.yahoo.com.tw',
42
- 'yahoo.com.vn' => 'smtp.mail.yahoo.com.vn',
43
- 'yahoo.co.nz' => 'smtp.mail.yahoo.com.au',
44
- 'yahoo.co.th' => 'smtp.mail.yahoo.co.th',
45
- 'yahoo.co.uk' => 'smtp.mail.yahoo.co.uk',
46
- 'yahoo.de' => 'smtp.mail.yahoo.de',
47
- 'yahoo.es' => 'smtp.correo.yahoo.es',
48
- 'yahoo.fr' => 'smtp.mail.yahoo.fr',
49
- 'yahoo.ie' => 'smtp.mail.yahoo.co.uk',
50
- 'yahoo.it' => 'smtp.mail.yahoo.it',
51
- 'zoho.com' => 'smtp.zoho.com',
52
- // from http://www.att.com/esupport/article.jsp?sid=KB401570&cv=801
53
- 'ameritech.net' => 'outbound.att.net',
54
- 'att.net' => 'outbound.att.net',
55
- 'bellsouth.net' => 'outbound.att.net',
56
- 'flash.net' => 'outbound.att.net',
57
- 'nvbell.net' => 'outbound.att.net',
58
- 'pacbell.net' => 'outbound.att.net',
59
- 'prodigy.net' => 'outbound.att.net',
60
- 'sbcglobal.net' => 'outbound.att.net',
61
- 'snet.net' => 'outbound.att.net',
62
- 'swbell.net' => 'outbound.att.net',
63
- 'wans.net' => 'outbound.att.net'
64
- );
65
- // if an email's mx is in this domain array, it is a known smtp server (dns lookup)
66
- // useful for custom domains that map to a mail service
67
- private static $mxMappings = array (
68
- '1and1help.com' => 'smtp.1and1.com',
69
- 'google.com' => 'smtp.gmail.com',
70
- 'Gmx.net' => 'mail.gmx.com',
71
- 'icloud.com' => 'smtp.mail.me.com',
72
- 'hotmail.com' => 'smtp.live.com',
73
- 'mx-eu.mail.am0.yahoodns.net' => 'smtp.mail.yahoo.com',
74
- // 'mail.protection.outlook.com' => 'smtp.office365.com',
75
- // 'mail.eo.outlook.com' => 'smtp.office365.com',
76
- 'outlook.com' => 'smtp.office365.com',
77
- 'biz.mail.am0.yahoodns.net' => 'smtp.bizmail.yahoo.com',
78
- 'BIZ.MAIL.YAHOO.com' => 'smtp.bizmail.yahoo.com',
79
- 'hushmail.com' => 'smtp.hushmail.com',
80
- 'gmx.net' => 'mail.gmx.com',
81
- 'mandrillapp.com' => 'smtp.mandrillapp.com',
82
- 'smtp.secureserver.net' => 'relay-hosting.secureserver.net',
83
- 'presmtp.ex1.secureserver.net' => 'smtp.ex1.secureserver.net',
84
- 'presmtp.ex2.secureserver.net' => 'smtp.ex2.secureserver.net',
85
- 'presmtp.ex3.secureserver.net' => 'smtp.ex2.secureserver.net',
86
- 'presmtp.ex4.secureserver.net' => 'smtp.ex2.secureserver.net',
87
- 'htvhosting.com' => 'mail.htvhosting.com'
88
- );
89
- public static function getSmtpFromEmail($hostname) {
90
- reset ( PostmanSmtpMappings::$emailDomain );
91
- foreach ( PostmanSmtpMappings::$emailDomain as $domain => $smtp ) {
92
- if (strcasecmp ( $hostname, $domain ) == 0) {
93
- return $smtp;
94
- }
95
- }
96
- return false;
97
- }
98
- public static function getSmtpFromMx($mx) {
99
- reset ( PostmanSmtpMappings::$mxMappings );
100
- foreach ( PostmanSmtpMappings::$mxMappings as $domain => $smtp ) {
101
- if (PostmanUtils::endswith ( $mx, $domain )) {
102
- return $smtp;
103
- }
104
- }
105
- return false;
106
- }
107
- }
108
- }
109
- if (! class_exists ( 'PostmanSmtpDiscovery' )) {
110
- class PostmanSmtpDiscovery {
111
-
112
- // private instance variables
113
- public $isGoogle;
114
- public $isGoDaddy;
115
- public $isWellKnownDomain;
116
- private $smtpServer;
117
- private $primaryMx;
118
- private $email;
119
- private $domain;
120
-
121
- /**
122
- * Constructor
123
- *
124
- * @param mixed $email
125
- */
126
- public function __construct($email) {
127
- $this->email = $email;
128
- $this->determineSmtpServer ( $email );
129
- $this->isGoogle = $this->smtpServer == 'smtp.gmail.com';
130
- $this->isGoDaddy = $this->smtpServer == 'relay-hosting.secureserver.net';
131
- }
132
- /**
133
- * The SMTP server we suggest to use - this is determined
134
- * by looking up the MX hosts for the domain.
135
- */
136
- public function getSmtpServer() {
137
- return $this->smtpServer;
138
- }
139
- public function getPrimaryMx() {
140
- return $this->primaryMx;
141
- }
142
- /**
143
- *
144
- * @param mixed $email
145
- * @return string|bool
146
- */
147
- private function validateEmail($email) {
148
- return PostmanUtils::validateEmail ( $email );
149
- }
150
- private function determineSmtpServer($email) {
151
- $hostname = substr ( strrchr ( $email, "@" ), 1 );
152
- $this->domain = $hostname;
153
- $smtp = PostmanSmtpMappings::getSmtpFromEmail ( $hostname );
154
- if ($smtp) {
155
- $this->smtpServer = $smtp;
156
- $this->isWellKnownDomain = true;
157
- return true;
158
- } else {
159
- $host = strtolower ( $this->findMxHostViaDns ( $hostname ) );
160
- if ($host) {
161
- $this->primaryMx = $host;
162
- $smtp = PostmanSmtpMappings::getSmtpFromMx ( $host );
163
- if ($smtp) {
164
- $this->smtpServer = $smtp;
165
- return true;
166
- } else {
167
- return false;
168
- }
169
- } else {
170
- return false;
171
- }
172
- }
173
- }
174
-
175
- /**
176
- * Uses getmxrr to retrieve the MX records of a hostname
177
- *
178
- * @param mixed $hostname
179
- * @return mixed|boolean
180
- */
181
- private function findMxHostViaDns($hostname) {
182
- if (function_exists ( 'getmxrr' )) {
183
- $b_mx_avail = getmxrr ( $hostname, $mx_records, $mx_weight );
184
- } else {
185
- $b_mx_avail = $this->getmxrr ( $hostname, $mx_records, $mx_weight );
186
- }
187
- if ($b_mx_avail && sizeof ( $mx_records ) > 0) {
188
- // copy mx records and weight into array $mxs
189
- $mxs = array ();
190
-
191
- for($i = 0; $i < count ( $mx_records ); $i ++) {
192
- $mxs [$mx_weight [$i]] = $mx_records [$i];
193
- }
194
-
195
- // sort array mxs to get servers with highest prio
196
- ksort ( $mxs, SORT_NUMERIC );
197
- reset ( $mxs );
198
- $mxs_vals = array_values ( $mxs );
199
- return array_shift ( $mxs_vals );
200
- } else {
201
- return false;
202
- }
203
- }
204
- /**
205
- * This is a custom implementation of mxrr for Windows PHP installations
206
- * which don't have this method natively.
207
- *
208
- * @param mixed $hostname
209
- * @param mixed $mxhosts
210
- * @param mixed $mxweight
211
- * @return boolean
212
- */
213
- function getmxrr($hostname, &$mxhosts, &$mxweight) {
214
- if (! is_array ( $mxhosts )) {
215
- $mxhosts = array ();
216
- }
217
- $hostname = escapeshellarg ( $hostname );
218
- if (! empty ( $hostname )) {
219
- $output = "";
220
- @exec ( "nslookup.exe -type=MX $hostname.", $output );
221
- $imx = - 1;
222
-
223
- foreach ( $output as $line ) {
224
- $imx ++;
225
- $parts = "";
226
- if (preg_match ( "/^$hostname\tMX preference = ([0-9]+), mail exchanger = (.*)$/", $line, $parts )) {
227
- $mxweight [$imx] = $parts [1];
228
- $mxhosts [$imx] = $parts [2];
229
- }
230
- }
231
- return ($imx != - 1);
232
- }
233
- return false;
234
- }
235
- }
236
- }
237
-
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ if (! class_exists ( 'PostmanSmtpMappings' )) {
7
+ class PostmanSmtpMappings {
8
+ // if an email is in this domain array, it is a known smtp server (easy lookup)
9
+ private static $emailDomain = array (
10
+ // from http://www.serversmtp.com/en/outgoing-mail-server-hostname
11
+ '1and1.com' => 'smtp.1and1.com',
12
+ 'airmail.net' => 'smtp.airmail.net',
13
+ 'aol.com' => 'smtp.aol.com',
14
+ 'Bluewin.ch' => 'Smtpauths.bluewin.ch',
15
+ 'Comcast.net' => 'Smtp.comcast.net',
16
+ 'Earthlink.net' => 'Smtpauth.earthlink.net',
17
+ 'gmail.com' => 'smtp.gmail.com',
18
+ 'Gmx.com' => 'mail.gmx.com',
19
+ 'Gmx.net' => 'mail.gmx.com',
20
+ 'Gmx.us' => 'mail.gmx.com',
21
+ 'hotmail.com' => 'smtp.live.com',
22
+ 'icloud.com' => 'smtp.mail.me.com',
23
+ 'mail.com' => 'smtp.mail.com',
24
+ 'ntlworld.com' => 'smtp.ntlworld.com',
25
+ 'rocketmail.com' => 'plus.smtp.mail.yahoo.com',
26
+ 'rogers.com' => 'smtp.broadband.rogers.com',
27
+ 'yahoo.ca' => 'smtp.mail.yahoo.ca',
28
+ 'yahoo.co.id' => 'smtp.mail.yahoo.co.id',
29
+ 'yahoo.co.in' => 'smtp.mail.yahoo.co.in',
30
+ 'yahoo.co.kr' => 'smtp.mail.yahoo.com',
31
+ 'yahoo.com' => 'smtp.mail.yahoo.com',
32
+ 'yahoo.com.ar' => 'smtp.mail.yahoo.com.ar',
33
+ 'yahoo.com.au' => 'smtp.mail.yahoo.com.au',
34
+ 'yahoo.com.br' => 'smtp.mail.yahoo.com.br',
35
+ 'yahoo.com.cn' => 'smtp.mail.yahoo.com.cn',
36
+ 'yahoo.com.hk' => 'smtp.mail.yahoo.com.hk',
37
+ 'yahoo.com.mx' => 'smtp.mail.yahoo.com',
38
+ 'yahoo.com.my' => 'smtp.mail.yahoo.com.my',
39
+ 'yahoo.com.ph' => 'smtp.mail.yahoo.com.ph',
40
+ 'yahoo.com.sg' => 'smtp.mail.yahoo.com.sg',
41
+ 'yahoo.com.tw' => 'smtp.mail.yahoo.com.tw',
42
+ 'yahoo.com.vn' => 'smtp.mail.yahoo.com.vn',
43
+ 'yahoo.co.nz' => 'smtp.mail.yahoo.com.au',
44
+ 'yahoo.co.th' => 'smtp.mail.yahoo.co.th',
45
+ 'yahoo.co.uk' => 'smtp.mail.yahoo.co.uk',
46
+ 'yahoo.de' => 'smtp.mail.yahoo.de',
47
+ 'yahoo.es' => 'smtp.correo.yahoo.es',
48
+ 'yahoo.fr' => 'smtp.mail.yahoo.fr',
49
+ 'yahoo.ie' => 'smtp.mail.yahoo.co.uk',
50
+ 'yahoo.it' => 'smtp.mail.yahoo.it',
51
+ 'zoho.com' => 'smtp.zoho.com',
52
+ // from http://www.att.com/esupport/article.jsp?sid=KB401570&cv=801
53
+ 'ameritech.net' => 'outbound.att.net',
54
+ 'att.net' => 'outbound.att.net',
55
+ 'bellsouth.net' => 'outbound.att.net',
56
+ 'flash.net' => 'outbound.att.net',
57
+ 'nvbell.net' => 'outbound.att.net',
58
+ 'pacbell.net' => 'outbound.att.net',
59
+ 'prodigy.net' => 'outbound.att.net',
60
+ 'sbcglobal.net' => 'outbound.att.net',
61
+ 'snet.net' => 'outbound.att.net',
62
+ 'swbell.net' => 'outbound.att.net',
63
+ 'wans.net' => 'outbound.att.net'
64
+ );
65
+ // if an email's mx is in this domain array, it is a known smtp server (dns lookup)
66
+ // useful for custom domains that map to a mail service
67
+ private static $mxMappings = array (
68
+ '1and1help.com' => 'smtp.1and1.com',
69
+ 'google.com' => 'smtp.gmail.com',
70
+ 'Gmx.net' => 'mail.gmx.com',
71
+ 'icloud.com' => 'smtp.mail.me.com',
72
+ 'hotmail.com' => 'smtp.live.com',
73
+ 'mx-eu.mail.am0.yahoodns.net' => 'smtp.mail.yahoo.com',
74
+ // 'mail.protection.outlook.com' => 'smtp.office365.com',
75
+ // 'mail.eo.outlook.com' => 'smtp.office365.com',
76
+ 'outlook.com' => 'smtp.office365.com',
77
+ 'biz.mail.am0.yahoodns.net' => 'smtp.bizmail.yahoo.com',
78
+ 'BIZ.MAIL.YAHOO.com' => 'smtp.bizmail.yahoo.com',
79
+ 'hushmail.com' => 'smtp.hushmail.com',
80
+ 'gmx.net' => 'mail.gmx.com',
81
+ 'mandrillapp.com' => 'smtp.mandrillapp.com',
82
+ 'smtp.secureserver.net' => 'relay-hosting.secureserver.net',
83
+ 'presmtp.ex1.secureserver.net' => 'smtp.ex1.secureserver.net',
84
+ 'presmtp.ex2.secureserver.net' => 'smtp.ex2.secureserver.net',
85
+ 'presmtp.ex3.secureserver.net' => 'smtp.ex2.secureserver.net',
86
+ 'presmtp.ex4.secureserver.net' => 'smtp.ex2.secureserver.net',
87
+ 'htvhosting.com' => 'mail.htvhosting.com'
88
+ );
89
+ public static function getSmtpFromEmail($hostname) {
90
+ reset ( PostmanSmtpMappings::$emailDomain );
91
+ foreach ( PostmanSmtpMappings::$emailDomain as $domain => $smtp ) {
92
+ if (strcasecmp ( $hostname, $domain ) == 0) {
93
+ return $smtp;
94
+ }
95
+ }
96
+ return false;
97
+ }
98
+ public static function getSmtpFromMx($mx) {
99
+ reset ( PostmanSmtpMappings::$mxMappings );
100
+ foreach ( PostmanSmtpMappings::$mxMappings as $domain => $smtp ) {
101
+ if (PostmanUtils::endswith ( $mx, $domain )) {
102
+ return $smtp;
103
+ }
104
+ }
105
+ return false;
106
+ }
107
+ }
108
+ }
109
+ if (! class_exists ( 'PostmanSmtpDiscovery' )) {
110
+ class PostmanSmtpDiscovery {
111
+
112
+ // private instance variables
113
+ public $isGoogle;
114
+ public $isGoDaddy;
115
+ public $isWellKnownDomain;
116
+ private $smtpServer;
117
+ private $primaryMx;
118
+ private $email;
119
+ private $domain;
120
+
121
+ /**
122
+ * Constructor
123
+ *
124
+ * @param mixed $email
125
+ */
126
+ public function __construct($email) {
127
+ $this->email = $email;
128
+ $this->determineSmtpServer ( $email );
129
+ $this->isGoogle = $this->smtpServer == 'smtp.gmail.com';
130
+ $this->isGoDaddy = $this->smtpServer == 'relay-hosting.secureserver.net';
131
+ }
132
+ /**
133
+ * The SMTP server we suggest to use - this is determined
134
+ * by looking up the MX hosts for the domain.
135
+ */
136
+ public function getSmtpServer() {
137
+ return $this->smtpServer;
138
+ }
139
+ public function getPrimaryMx() {
140
+ return $this->primaryMx;
141
+ }
142
+ /**
143
+ *
144
+ * @param mixed $email
145
+ * @return string|bool
146
+ */
147
+ private function validateEmail($email) {
148
+ return PostmanUtils::validateEmail ( $email );
149
+ }
150
+ private function determineSmtpServer($email) {
151
+ $hostname = substr ( strrchr ( $email, "@" ), 1 );
152
+ $this->domain = $hostname;
153
+ $smtp = PostmanSmtpMappings::getSmtpFromEmail ( $hostname );
154
+ if ($smtp) {
155
+ $this->smtpServer = $smtp;
156
+ $this->isWellKnownDomain = true;
157
+ return true;
158
+ } else {
159
+ $host = strtolower ( $this->findMxHostViaDns ( $hostname ) );
160
+ if ($host) {
161
+ $this->primaryMx = $host;
162
+ $smtp = PostmanSmtpMappings::getSmtpFromMx ( $host );
163
+ if ($smtp) {
164
+ $this->smtpServer = $smtp;
165
+ return true;
166
+ } else {
167
+ return false;
168
+ }
169
+ } else {
170
+ return false;
171
+ }
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Uses getmxrr to retrieve the MX records of a hostname
177
+ *
178
+ * @param mixed $hostname
179
+ * @return mixed|boolean
180
+ */
181
+ private function findMxHostViaDns($hostname) {
182
+ if (function_exists ( 'getmxrr' )) {
183
+ $b_mx_avail = getmxrr ( $hostname, $mx_records, $mx_weight );
184
+ } else {
185
+ $b_mx_avail = $this->getmxrr ( $hostname, $mx_records, $mx_weight );
186
+ }
187
+ if ($b_mx_avail && sizeof ( $mx_records ) > 0) {
188
+ // copy mx records and weight into array $mxs
189
+ $mxs = array ();
190
+
191
+ for($i = 0; $i < count ( $mx_records ); $i ++) {
192
+ $mxs [$mx_weight [$i]] = $mx_records [$i];
193
+ }
194
+
195
+ // sort array mxs to get servers with highest prio
196
+ ksort ( $mxs, SORT_NUMERIC );
197
+ reset ( $mxs );
198
+ $mxs_vals = array_values ( $mxs );
199
+ return array_shift ( $mxs_vals );
200
+ } else {
201
+ return false;
202
+ }
203
+ }
204
+ /**
205
+ * This is a custom implementation of mxrr for Windows PHP installations
206
+ * which don't have this method natively.
207
+ *
208
+ * @param mixed $hostname
209
+ * @param mixed $mxhosts
210
+ * @param mixed $mxweight
211
+ * @return boolean
212
+ */
213
+ function getmxrr($hostname, &$mxhosts, &$mxweight) {
214
+ if (! is_array ( $mxhosts )) {
215
+ $mxhosts = array ();
216
+ }
217
+ $hostname = escapeshellarg ( $hostname );
218
+ if (! empty ( $hostname )) {
219
+ $output = "";
220
+ @exec ( "nslookup.exe -type=MX $hostname.", $output );
221
+ $imx = - 1;
222
+
223
+ foreach ( $output as $line ) {
224
+ $imx ++;
225
+ $parts = "";
226
+ if (preg_match ( "/^$hostname\tMX preference = ([0-9]+), mail exchanger = (.*)$/", $line, $parts )) {
227
+ $mxweight [$imx] = $parts [1];
228
+ $mxhosts [$imx] = $parts [2];
229
+ }
230
+ }
231
+ return ($imx != - 1);
232
+ }
233
+ return false;
234
+ }
235
+ }
236
+ }
237
+
Postman/Postman-Configuration/postman_manual_config.js CHANGED
@@ -1,112 +1,112 @@
1
- var transports = [];
2
-
3
- jQuery(document).ready(
4
- function($) {
5
-
6
- // display password on entry
7
- enablePasswordDisplayOnEntry('input_basic_auth_password',
8
- 'togglePasswordField');
9
-
10
- // tabs
11
- jQuery("#config_tabs").tabs( {
12
-
13
- activate: function( event ,ui ) {
14
-
15
- jQuery( ui.oldTab ).addClass( 'visited-config-ui-tab' );
16
-
17
- }
18
-
19
- } );
20
-
21
- // on first viewing, determine whether to show password or
22
- // oauth section
23
- reloadOauthSection();
24
-
25
- // add an event on the transport input field
26
- // when the user changes the transport, determine whether
27
- // to show or hide the SMTP Settings
28
- jQuery('select#input_transport_type').change(function() {
29
- hide('#wizard_oauth2_help');
30
- reloadOauthSection();
31
- switchBetweenPasswordAndOAuth();
32
- });
33
-
34
- jQuery('select#input_notification_service').change(function() {
35
- var selected = $( this ).val();
36
-
37
- if ( selected == 'default' ) {
38
- $('#slack_cred').fadeOut('fast');
39
- $('#pushover_cred').fadeOut('fast');
40
- }
41
-
42
- if ( selected == 'pushover' ) {
43
- $('#slack_cred').fadeOut('fast');
44
- $('#pushover_cred').fadeIn();
45
- }
46
-
47
- if ( selected == 'slack' ) {
48
- $('#pushover_cred').fadeOut('fast');
49
- $('#slack_cred').fadeIn();
50
- }
51
-
52
- Hook.call( 'post_smtp_notification_change', selected );
53
-
54
- });
55
-
56
-
57
- // add an event on the authentication input field
58
- // on user changing the auth type, determine whether to show
59
- // password or oauth section
60
- jQuery('select#input_auth_type').change(function() {
61
- switchBetweenPasswordAndOAuth();
62
- doneTyping();
63
- });
64
-
65
- // setup before functions
66
- var typingTimer; // timer identifier
67
- var doneTypingInterval = 250; // time in ms, 5 second for
68
- // example
69
-
70
- // add an event on the hostname input field
71
- // on keyup, start the countdown
72
- jQuery(post_smtp_localize.postman_hostname_element_name).keyup(function() {
73
- clearTimeout(typingTimer);
74
- if (jQuery(post_smtp_localize.postman_hostname_element_name).val) {
75
- typingTimer = setTimeout(doneTyping, doneTypingInterval);
76
- }
77
- });
78
-
79
- // user is "finished typing," do something
80
- function doneTyping() {
81
- if (jQuery(post_smtp_localize.postman_input_auth_type).val() == 'oauth2') {
82
- reloadOauthSection();
83
- }
84
- }
85
- });
86
-
87
- function reloadOauthSection() {
88
- var hostname = jQuery(post_smtp_localize.postman_hostname_element_name).val();
89
- var transport = jQuery('#input_transport_type').val();
90
- var authtype = jQuery('select#input_auth_type').val();
91
- var security = jQuery('#security').val();
92
- var data = {
93
- 'action' : 'manual_config',
94
- 'auth_type' : authtype,
95
- 'hostname' : hostname,
96
- 'transport' : transport,
97
- 'security' : security
98
- };
99
- jQuery.post(ajaxurl, data, function(response) {
100
- if (response.success) {
101
- handleConfigurationResponse(response);
102
- }
103
- }).fail(function(response) {
104
- ajaxFailed(response);
105
- });
106
- }
107
- function switchBetweenPasswordAndOAuth() {
108
- var transportName = jQuery('select#input_transport_type').val();
109
- transports.forEach(function(item) {
110
- item.handleTransportChange(transportName);
111
- });
112
- }
1
+ var transports = [];
2
+
3
+ jQuery(document).ready(
4
+ function($) {
5
+
6
+ // display password on entry
7
+ enablePasswordDisplayOnEntry('input_basic_auth_password',
8
+ 'togglePasswordField');
9
+
10
+ // tabs
11
+ jQuery("#config_tabs").tabs( {
12
+
13
+ activate: function( event ,ui ) {
14
+
15
+ jQuery( ui.oldTab ).addClass( 'visited-config-ui-tab' );
16
+
17
+ }
18
+
19
+ } );
20
+
21
+ // on first viewing, determine whether to show password or
22
+ // oauth section
23
+ reloadOauthSection();
24
+
25
+ // add an event on the transport input field
26
+ // when the user changes the transport, determine whether
27
+ // to show or hide the SMTP Settings
28
+ jQuery('select#input_transport_type').change(function() {
29
+ hide('#wizard_oauth2_help');
30
+ reloadOauthSection();
31
+ switchBetweenPasswordAndOAuth();
32
+ });
33
+
34
+ jQuery('select#input_notification_service').change(function() {
35
+ var selected = $( this ).val();
36
+
37
+ if ( selected == 'default' ) {
38
+ $('#slack_cred').fadeOut('fast');
39
+ $('#pushover_cred').fadeOut('fast');
40
+ }
41
+
42
+ if ( selected == 'pushover' ) {
43
+ $('#slack_cred').fadeOut('fast');
44
+ $('#pushover_cred').fadeIn();
45
+ }
46
+
47
+ if ( selected == 'slack' ) {
48
+ $('#pushover_cred').fadeOut('fast');
49
+ $('#slack_cred').fadeIn();
50
+ }
51
+
52
+ Hook.call( 'post_smtp_notification_change', selected );
53
+
54
+ });
55
+
56
+
57
+ // add an event on the authentication input field
58
+ // on user changing the auth type, determine whether to show
59
+ // password or oauth section
60
+ jQuery('select#input_auth_type').change(function() {
61
+ switchBetweenPasswordAndOAuth();
62
+ doneTyping();
63
+ });
64
+
65
+ // setup before functions
66
+ var typingTimer; // timer identifier
67
+ var doneTypingInterval = 250; // time in ms, 5 second for
68
+ // example
69
+
70
+ // add an event on the hostname input field
71
+ // on keyup, start the countdown
72
+ jQuery(post_smtp_localize.postman_hostname_element_name).keyup(function() {
73
+ clearTimeout(typingTimer);
74
+ if (jQuery(post_smtp_localize.postman_hostname_element_name).val) {
75
+ typingTimer = setTimeout(doneTyping, doneTypingInterval);
76
+ }
77
+ });
78
+
79
+ // user is "finished typing," do something
80
+ function doneTyping() {
81
+ if (jQuery(post_smtp_localize.postman_input_auth_type).val() == 'oauth2') {
82
+ reloadOauthSection();
83
+ }
84
+ }
85
+ });
86
+
87
+ function reloadOauthSection() {
88
+ var hostname = jQuery(post_smtp_localize.postman_hostname_element_name).val();
89
+ var transport = jQuery('#input_transport_type').val();
90
+ var authtype = jQuery('select#input_auth_type').val();
91
+ var security = jQuery('#security').val();
92
+ var data = {
93
+ 'action' : 'manual_config',
94
+ 'auth_type' : authtype,
95
+ 'hostname' : hostname,
96
+ 'transport' : transport,
97
+ 'security' : security
98
+ };
99
+ jQuery.post(ajaxurl, data, function(response) {
100
+ if (response.success) {
101
+ handleConfigurationResponse(response);
102
+ }
103
+ }).fail(function(response) {
104
+ ajaxFailed(response);
105
+ });
106
+ }
107
+ function switchBetweenPasswordAndOAuth() {
108
+ var transportName = jQuery('select#input_transport_type').val();
109
+ transports.forEach(function(item) {
110
+ item.handleTransportChange(transportName);
111
+ });
112
+ }
Postman/Postman-Configuration/postman_wizard.js CHANGED
@@ -1,697 +1,697 @@
1
- var transports = [];
2
-
3
- connectivtyTestResults = {};
4
- portTestInProgress = false;
5
-
6
- /**
7
- * Functions to run on document load
8
- */
9
- jQuery(document).ready(function() {
10
- jQuery(post_smtp_localize.postman_input_sender_email).focus();
11
- initializeJQuerySteps();
12
- // add an event on the plugin selection
13
- jQuery('input[name="input_plugin"]').click(function() {
14
- getConfiguration();
15
- });
16
-
17
- // add an event on the transport input field
18
- // when the user changes the transport, determine whether
19
- // to show or hide the SMTP Settings
20
- jQuery('select#input_transport_type').change(function() {
21
- hide('#wizard_oauth2_help');
22
- reloadOauthSection();
23
- switchBetweenPasswordAndOAuth();
24
- });
25
-
26
- });
27
-
28
- function checkGoDaddyAndCheckEmail(email) {
29
- hide('#godaddy_block');
30
- hide('#godaddy_spf_required');
31
- // are we hosted on GoDaddy? check.
32
- var data = {
33
- 'action' : 'postman_wizard_port_test',
34
- 'hostname' : 'relay-hosting.secureserver.net',
35
- 'port' : 25,
36
- 'timeout' : 3,
37
- 'security' : jQuery('#security').val(),
38
- };
39
- goDaddy = 'unknown';
40
- checkedEmail = false;
41
- jQuery.post(ajaxurl, data, function(response) {
42
- if (postmanValidateAjaxResponseWithPopup(response)) {
43
- checkEmail(response.success, email);
44
- }
45
- }).fail(function(response) {
46
- ajaxFailed(response);
47
- });
48
- }
49
-
50
- function checkEmail(goDaddyHostDetected, email) {
51
- var data = {
52
- 'action' : 'postman_check_email',
53
- 'go_daddy' : goDaddyHostDetected,
54
- 'email' : email,
55
- 'security' : jQuery('#security').val()
56
- };
57
- jQuery.post(
58
- ajaxurl,
59
- data,
60
- function(response) {
61
- if (postmanValidateAjaxResponseWithPopup(response)) {
62
- checkedEmail = true;
63
- smtpDiscovery = response.data;
64
- if (response.data.hostname != null
65
- && response.data.hostname) {
66
- jQuery(post_smtp_localize.postman_hostname_element_name).val(
67
- response.data.hostname);
68
- }
69
- enableSmtpHostnameInput(goDaddyHostDetected);
70
- }
71
- }).fail(function(response) {
72
- ajaxFailed(response);
73
- });
74
- }
75
-
76
- function enableSmtpHostnameInput(goDaddyHostDetected) {
77
- if (goDaddyHostDetected && !smtpDiscovery.is_google) {
78
- // this is a godaddy server and we are using a godaddy smtp server
79
- // (gmail excepted)
80
- if (smtpDiscovery.is_go_daddy) {
81
- // we detected GoDaddy, and the user has entered a GoDaddy hosted
82
- // email
83
- } else if (smtpDiscovery.is_well_known) {
84
- // this is a godaddy server but the SMTP must be the email
85
- // service
86
- show('#godaddy_block');
87
- } else {
88
- // this is a godaddy server and we're using a (possibly) custom
89
- // domain
90
- show('#godaddy_spf_required');
91
- }
92
- }
93
- enable('#input_hostname');
94
- jQuery('li').removeClass('disabled');
95
- hideLoaderIcon();
96
- }
97
-
98
- /**
99
- * Initialize the Steps wizard
100
- */
101
- function initializeJQuerySteps() {
102
- jQuery("#postman_wizard").steps(
103
- {
104
- bodyTag : "fieldset",
105
- headerTag : "h5",
106
- transitionEffect : "slideLeft",
107
- stepsOrientation : "vertical",
108
- autoFocus : true,
109
- startIndex : parseInt(postman_setup_wizard.start_page),
110
- labels : {
111
- current : post_smtp_localize.steps_current_step,
112
- pagination : post_smtp_localize.steps_pagination,
113
- finish : post_smtp_localize.steps_finish,
114
- next : post_smtp_localize.steps_next,
115
- previous : post_smtp_localize.steps_previous,
116
- loading : post_smtp_localize.steps_loading
117
- },
118
- onStepChanging : function(event, currentIndex, newIndex) {
119
-
120
- var response = handleStepChange( event, currentIndex, newIndex, jQuery( this ) );
121
-
122
- if( response ) {
123
-
124
- if( !jQuery( `#postman_wizard-t-${currentIndex} span` ).hasClass( 'dashicons' ) )
125
- jQuery( `#postman_wizard-t-${currentIndex}` ).append( '<span class="ps-right dashicons dashicons-yes-alt"></span>' );
126
-
127
- }
128
-
129
- return response;
130
-
131
- },
132
- onInit : function() {
133
-
134
- if( !jQuery( `#postman_wizard-t-0 span` ).hasClass( 'dashicons' ) )
135
- jQuery( '#postman_wizard-t-0' ).append( '<span class="ps-right dashicons dashicons-yes-alt"></span>' );
136
-
137
- jQuery(post_smtp_localize.postman_input_sender_email).focus();
138
-
139
- },
140
- onStepChanged : function(event, currentIndex, priorIndex) {
141
- return postHandleStepChange(event, currentIndex,
142
- priorIndex, jQuery(this));
143
- },
144
- onFinishing : function(event, currentIndex) {
145
- var form = jQuery(this);
146
-
147
- // Disable validation on fields that
148
- // are disabled.
149
- // At this point it's recommended to
150
- // do an overall check (mean
151
- // ignoring
152
- // only disabled fields)
153
- // form.validate().settings.ignore =
154
- // ":disabled";
155
-
156
- // Start validation; Prevent form
157
- // submission if false
158
- return form.valid();
159
- },
160
- onFinished : function(event, currentIndex) {
161
- var form = jQuery(this);
162
-
163
- // Submit form input
164
- form.submit();
165
- }
166
- }).validate({
167
- errorPlacement : function(error, element) {
168
- element.before(error);
169
- }
170
- });
171
- }
172
-
173
- function handleStepChange(event, currentIndex, newIndex, form) {
174
- // Always allow going backward even if
175
- // the current step contains invalid fields!
176
- if (currentIndex > newIndex) {
177
- if (currentIndex === 2 && !(checkedEmail)) {
178
- return false;
179
- }
180
- if (currentIndex === 3 && portTestInProgress) {
181
- return false;
182
- }
183
- return true;
184
- }
185
-
186
- // Clean up if user went backward
187
- // before
188
- if (currentIndex < newIndex) {
189
- // To remove error styles
190
- jQuery(".body:eq(" + newIndex + ") label.error", form).remove();
191
- jQuery(".body:eq(" + newIndex + ") .error", form).removeClass("error");
192
- }
193
-
194
- // Disable validation on fields that
195
- // are disabled or hidden.
196
- form.validate().settings.ignore = ":disabled,:hidden";
197
-
198
- // Start validation; Prevent going
199
- // forward if false
200
- valid = form.valid();
201
- if (!valid) {
202
- return false;
203
- }
204
-
205
- if (currentIndex === 1) {
206
- // page 1 : look-up the email
207
- // address for the smtp server
208
- checkGoDaddyAndCheckEmail(jQuery(post_smtp_localize.postman_input_sender_email).val());
209
-
210
- } else if (currentIndex === 2) {
211
-
212
- if (!(checkedEmail)) {
213
- return false;
214
- }
215
- // page 2 : check the port
216
- portsChecked = 0;
217
- portsToCheck = 0;
218
- totalAvail = 0;
219
-
220
- getHostsToCheck(jQuery(post_smtp_localize.postman_hostname_element_name).val());
221
-
222
- } else if (currentIndex === 3) {
223
-
224
- // user has clicked next but we haven't finished the check
225
- if (portTestInProgress) {
226
- return false;
227
- }
228
- // or all ports are unavailable
229
- if (portCheckBlocksUi) {
230
- return false;
231
- }
232
- valid = form.valid();
233
- if (!valid) {
234
- return false;
235
- }
236
- var chosenPort = jQuery(post_smtp_localize.postman_port_element_name).val();
237
- var hostname = jQuery(post_smtp_localize.postman_hostname_element_name).val();
238
- var authType = jQuery(post_smtp_localize.postman_input_auth_type).val()
239
-
240
- }
241
-
242
- return true;
243
- }
244
-
245
- function postHandleStepChange(event, currentIndex, priorIndex, myself) {
246
- var chosenPort = jQuery('#input_auth_type').val();
247
- // Suppress (skip) "Warning" step if
248
- // the user is old enough and wants
249
- // to the previous step.
250
- if (currentIndex === 2) {
251
- jQuery(post_smtp_localize.postman_hostname_element_name).focus();
252
- // this is the second place i disable the next button but Steps
253
- // re-enables it after the screen slides
254
- if (priorIndex === 1) {
255
- disable('#input_hostname');
256
- jQuery('li').addClass('disabled');
257
- showLoaderIcon();
258
- }
259
- }
260
- if (currentIndex === 3) {
261
- if (priorIndex === 2) {
262
- // this is the second place i disable the next button but Steps
263
- // re-enables it after the screen slides
264
- jQuery('li').addClass('disabled');
265
- showLoaderIcon();
266
- }
267
- }
268
- if (currentIndex === 4) {
269
- if (redirectUrlWarning) {
270
- alert(post_smtp_localize.postman_wizard_bad_redirect_url);
271
- }
272
- if (chosenPort == 'none') {
273
- if (priorIndex === 5) {
274
-
275
- myself.steps("previous");
276
- return;
277
- }
278
- myself.steps("next");
279
- }
280
- }
281
-
282
- }
283
-
284
- /**
285
- * Asks the server for a List of sockets to perform port checks upon.
286
- *
287
- * @param hostname
288
- */
289
- function getHostsToCheck(hostname) {
290
- jQuery('table#wizard_port_test').html('');
291
- jQuery('#wizard_recommendation').html('');
292
- hide('.user_override');
293
- hide('#smtp_not_secure');
294
- hide('#smtp_mitm');
295
- connectivtyTestResults = {};
296
- portCheckBlocksUi = true;
297
- portTestInProgress = true;
298
- var data = {
299
- 'action' : 'postman_get_hosts_to_test',
300
- 'hostname' : hostname,
301
- 'original_smtp_server' : smtpDiscovery.hostname,
302
- 'security' : jQuery('#security').val(),
303
- };
304
- jQuery.post(ajaxurl, data, function(response) {
305
- if (postmanValidateAjaxResponseWithPopup(response)) {
306
- handleHostsToCheckResponse(response.data);
307
- }
308
- }).fail(function(response) {
309
- ajaxFailed(response);
310
- });
311
- }
312
-
313
- /**
314
- * Handles the response from the server of the list of sockets to check.
315
- *
316
- * @param hostname
317
- * @param response
318
- */
319
- function handleHostsToCheckResponse(response) {
320
- for ( var x in response.hosts) {
321
- var hostname = response.hosts[x].host;
322
- var port = response.hosts[x].port;
323
- var transport = response.hosts[x].transport_id;
324
- var logoURL = response.hosts[x].logo_url;
325
- portsToCheck++;
326
- show('#connectivity_test_status');
327
- updateStatus(postman_port_test.in_progress + " " + portsToCheck);
328
- var data = {
329
- 'action' : 'postman_wizard_port_test',
330
- 'hostname' : hostname,
331
- 'port' : port,
332
- 'transport' : transport,
333
- 'logo_url': logoURL,
334
- 'security' : jQuery('#security').val(),
335
- };
336
- postThePortTest(hostname, port, data);
337
- }
338
- }
339
-
340
- /**
341
- * Asks the server to run a connectivity test on the given port
342
- *
343
- * @param hostname
344
- * @param port
345
- * @param data
346
- */
347
- function postThePortTest(hostname, port, data) {
348
- jQuery.post(ajaxurl, data, function(response) {
349
- if (postmanValidateAjaxResponseWithPopup(response)) {
350
- handlePortTestResponse(hostname, port, data, response);
351
- }
352
- }).fail(function(response) {
353
- ajaxFailed(response);
354
- portsChecked++;
355
- afterPortsChecked();
356
- });
357
- }
358
-
359
- /**
360
- * Handles the result of the port test
361
- *
362
- * @param hostname
363
- * @param port
364
- * @param data
365
- * @param response
366
- */
367
- function handlePortTestResponse(hostname, port, data, response) {
368
- if (!response.data.try_smtps) {
369
- portsChecked++;
370
- updateStatus(postman_port_test.in_progress + " "
371
- + (portsToCheck - portsChecked));
372
- connectivtyTestResults[hostname + '_' + port] = response.data;
373
- if (response.success) {
374
- // a totalAvail > 0 is our signal to go to the next step
375
- totalAvail++;
376
- }
377
- afterPortsChecked();
378
- } else {
379
- // SMTP failed, try again on the SMTPS port
380
- data['action'] = 'postman_wizard_port_test_smtps';
381
- data['security'] = jQuery('#security').val();
382
- postThePortTest(hostname, port, data);
383
- }
384
- }
385
-
386
- /**
387
- *
388
- * @param message
389
- */
390
- function updateStatus(message) {
391
- jQuery('#port_test_status').html(
392
- '<span style="color:blue">' + message + '</span>');
393
- }
394
-
395
- /**
396
- * This functions runs after ALL the ports have been checked. It's chief
397
- * function is to push the results of the port test back to the server to get a
398
- * suggested configuration.
399
- */
400
- function afterPortsChecked() {
401
- if (portsChecked >= portsToCheck) {
402
- hideLoaderIcon();
403
- if (totalAvail != 0) {
404
- jQuery('li').removeClass('disabled');
405
- portCheckBlocksUi = false;
406
- }
407
- var data = {
408
- 'action' : 'get_wizard_configuration_options',
409
- 'original_smtp_server' : smtpDiscovery.hostname,
410
- 'host_data' : connectivtyTestResults,
411
- 'security': jQuery('#security').val()
412
- };
413
- postTheConfigurationRequest(data);
414
- hide('#connectivity_test_status');
415
- }
416
- }
417
-
418
- function userOverrideMenu() {
419
- disable('input.user_socket_override');
420
- disable('input.user_auth_override');
421
- var data = {
422
- 'action' : 'get_wizard_configuration_options',
423
- 'original_smtp_server' : smtpDiscovery.hostname,
424
- 'user_port_override' : jQuery(
425
- "input:radio[name='user_socket_override']:checked").val(),
426
- 'user_auth_override' : jQuery(
427
- "input:radio[name='user_auth_override']:checked").val(),
428
- 'host_data' : connectivtyTestResults,
429
- 'security' : jQuery('#security').val()
430
- };
431
- postTheConfigurationRequest(data);
432
- }
433
-
434
- function postTheConfigurationRequest(data) {
435
- jQuery.post(
436
- ajaxurl,
437
- data,
438
- function(response) {
439
- if (postmanValidateAjaxResponseWithPopup(response)) {
440
- portTestInProgress = false;
441
- var $message = '';
442
- if (response.success) {
443
- $message = '<span style="color:green">'
444
- + response.data.configuration.message
445
- + '</span>';
446
- handleConfigurationResponse(response.data);
447
- enable('input.user_socket_override');
448
- enable('input.user_auth_override');
449
- // enable both next/back buttons
450
- jQuery('li').removeClass('disabled');
451
- } else {
452
- $message = '<span style="color:red">'
453
- + response.data.configuration.message
454
- + '</span>';
455
- // enable the back button only
456
- jQuery('li').removeClass('disabled');
457
- jQuery('li + li').addClass('disabled');
458
- }
459
- if (!response.data.configuration.user_override) {
460
- jQuery('#wizard_recommendation').append($message);
461
- }
462
- }
463
- }).fail(function(response) {
464
- ajaxFailed(response);
465
- });
466
- }
467
- function handleConfigurationResponse(response) {
468
-
469
- var html = '';
470
- var authHtml = '';
471
-
472
- jQuery('#input_transport_type').val(response.configuration.transport_type);
473
- transports.forEach(function(item) {
474
- item.handleConfigurationResponse(response);
475
- })
476
-
477
- // this stuff builds the options and is common to all transports
478
- // populate user Port Override menu
479
- show('.user_override');
480
- var el1 = jQuery('#user_socket_override');
481
- el1.html('');
482
-
483
- var columns = 1;
484
-
485
- for (i = 0; i < response.override_menu.length; i++) {
486
-
487
- response.override_menu[i].data = response.override_menu[i].data !== null ? response.override_menu[i].data : false;
488
-
489
- if( columns == 1 ) {
490
- html += "<div class='ps-socket-wizad-row'>";
491
- }
492
-
493
- html += buildRadioButtonGroup(
494
- 'user_socket_override',
495
- response.override_menu[i].selected,
496
- response.override_menu[i].value,
497
- response.override_menu[i].description,
498
- response.override_menu[i].secure,
499
- response.override_menu[i].data
500
- );
501
-
502
- if( columns == 3 ) {
503
- html += '</div>';
504
- columns = 0;
505
- }
506
-
507
- columns++;
508
-
509
- // populate user Auth Override menu
510
- if (response.override_menu[i].selected) {
511
- if (response.override_menu[i].mitm) {
512
- show('#smtp_mitm');
513
- jQuery('#smtp_mitm')
514
- .html(
515
- sprintf(
516
- postman_port_test.mitm,
517
- response.override_menu[i].reported_hostname_domain_only,
518
- response.override_menu[i].hostname_domain_only));
519
- } else {
520
- hide('#smtp_mitm');
521
- }
522
- var el2 = jQuery('#user_auth_override');
523
- el2.html('');
524
- hide('#smtp_not_secure');
525
- for (j = 0; j < response.override_menu[i].auth_items.length; j++) {
526
-
527
- authHtml += buildRadioButtonGroup(
528
- 'user_auth_override',
529
- response.override_menu[i].auth_items[j].selected,
530
- response.override_menu[i].auth_items[j].value,
531
- response.override_menu[i].auth_items[j].name,
532
- false
533
- );
534
-
535
- if (response.override_menu[i].auth_items[j].selected
536
- && !response.override_menu[i].secure
537
- && response.override_menu[i].auth_items[j].value != 'none') {
538
- show('#smtp_not_secure');
539
- }
540
- }
541
- }
542
-
543
-
544
- }
545
-
546
- el1.append( html );
547
- el2.append( authHtml );
548
-
549
- jQuery.fn.suggestPro();
550
-
551
- jQuery('select#input_notification_service').change(function() {
552
- var selected = jQuery( this ).val();
553
-
554
- if ( selected == 'default' ) {
555
- jQuery('#slack_cred').fadeOut('fast');
556
- jQuery('#pushover_cred').fadeOut('fast');
557
- }
558
-
559
- if ( selected == 'pushover' ) {
560
- jQuery('#slack_cred').fadeOut('fast');
561
- jQuery('#pushover_cred').fadeIn();
562
- }
563
-
564
- if ( selected == 'slack' ) {
565
- jQuery('#pushover_cred').fadeOut('fast');
566
- jQuery('#slack_cred').fadeIn();
567
- }
568
-
569
- Hook.call( 'post_smtp_notification_change', selected );
570
- });
571
-
572
- // Add an event on Socket Selection/ Switching
573
- jQuery( 'input.user_socket_override' ).change( function() {
574
- userOverrideMenu();
575
- } );
576
-
577
- // Add an event on Socket's Auth Type Selection/ Switching
578
- jQuery( 'input.user_auth_override' ).change( function() {
579
- userOverrideMenu();
580
- } );
581
- }
582
-
583
- /**
584
- *
585
- * @param {*} radioGroupName
586
- * @param {*} isSelected
587
- * @param {*} value
588
- * @param {*} label
589
- * @param {*} isSecure
590
- * @param {*} data
591
- * @returns
592
- *
593
- * @since 2.1 Returns html instead of appending
594
- */
595
- function buildRadioButtonGroup( radioGroupName, isSelected, value, label, isSecure, data = '' ) {
596
-
597
- var radioInputValue = ' value="' + value + '"';
598
- var radioInputChecked = '';
599
- var secureIcon = '';
600
- var logoTag = '';
601
- var html = '';
602
- var recommendedBlock = '';
603
- var relativeClass = '';
604
-
605
- if (isSelected) {
606
- radioInputChecked = ' checked = "checked"';
607
- }
608
-
609
- if (isSecure) {
610
- secureIcon = '&#x1f512;';
611
- }
612
-
613
- if( data.logo_url && data.logo_url !== undefined ) {
614
-
615
- if( label == 'Sendinblue' ) {
616
-
617
- relativeClass = 'ps-sib';
618
- recommendedBlock = `
619
- <img src="${postman.assets}images/icons/recommended.png" class="ps-sib-recommended" />
620
- `;
621
-
622
- }
623
-
624
- logoTag = `
625
- <div class='ps-single-socket-outer ${relativeClass}'>
626
- ${recommendedBlock}
627
- <img src='${data.logo_url}' class='ps-wizard-socket-logo' width='165px' />
628
- </div>
629
- `;
630
-
631
- }
632
-
633
- html = `
634
- <label>
635
- ${logoTag}
636
- <input class="${radioGroupName}" type="radio" name="${radioGroupName}"${radioInputChecked} ${radioInputValue} />
637
- ${secureIcon + label}
638
- </label>
639
- `;
640
-
641
- return html;
642
-
643
- }
644
-
645
- /**
646
- * Handles population of the configuration based on the options set in a
647
- * 3rd-party SMTP plugin
648
- */
649
- function getConfiguration() {
650
- var plugin = jQuery('input[name="input_plugin"]' + ':checked').val();
651
- if (plugin != '') {
652
- var data = {
653
- 'action' : 'import_configuration',
654
- 'plugin' : plugin,
655
- 'security' : jQuery('#security').val(),
656
- };
657
- jQuery
658
- .post(
659
- ajaxurl,
660
- data,
661
- function(response) {
662
- if (response.success) {
663
- jQuery('select#input_transport_type').val(
664
- 'smtp');
665
- jQuery(post_smtp_localize.postman_input_sender_email).val(
666
- response.sender_email);
667
- jQuery(post_smtp_localize.postman_input_sender_name).val(
668
- response.sender_name);
669
- jQuery(post_smtp_localize.postman_hostname_element_name).val(
670
- response.hostname);
671
- jQuery(post_smtp_localize.postman_port_element_name).val(
672
- response.port);
673
- jQuery(post_smtp_localize.postman_input_auth_type).val(
674
- response.auth_type);
675
- jQuery('#input_enc_type')
676
- .val(response.enc_type);
677
- jQuery(post_smtp_localize.postman_input_basic_username).val(
678
- response.basic_auth_username);
679
- jQuery(post_smtp_localize.postman_input_basic_password).val(
680
- response.basic_auth_password);
681
- switchBetweenPasswordAndOAuth();
682
- }
683
- }).fail(function(response) {
684
- ajaxFailed(response);
685
- });
686
- } else {
687
- jQuery(post_smtp_localize.postman_input_sender_email).val('');
688
- jQuery(post_smtp_localize.postman_input_sender_name).val('');
689
- jQuery(post_smtp_localize.postman_input_basic_username).val('');
690
- jQuery(post_smtp_localize.postman_input_basic_password).val('');
691
- jQuery(post_smtp_localize.postman_hostname_element_name).val('');
692
- jQuery(post_smtp_localize.postman_port_element_name).val('');
693
- jQuery(post_smtp_localize.postman_input_auth_type).val('none');
694
- jQuery(post_smtp_localize.postman_enc_for_password_el).val('none');
695
- switchBetweenPasswordAndOAuth();
696
- }
697
- }
1
+ var transports = [];
2
+
3
+ connectivtyTestResults = {};
4
+ portTestInProgress = false;
5
+
6
+ /**
7
+ * Functions to run on document load
8
+ */
9
+ jQuery(document).ready(function() {
10
+ jQuery(post_smtp_localize.postman_input_sender_email).focus();
11
+ initializeJQuerySteps();
12
+ // add an event on the plugin selection
13
+ jQuery('input[name="input_plugin"]').click(function() {
14
+ getConfiguration();
15
+ });
16
+
17
+ // add an event on the transport input field
18
+ // when the user changes the transport, determine whether
19
+ // to show or hide the SMTP Settings
20
+ jQuery('select#input_transport_type').change(function() {
21
+ hide('#wizard_oauth2_help');
22
+ reloadOauthSection();
23
+ switchBetweenPasswordAndOAuth();
24
+ });
25
+
26
+ });
27
+
28
+ function checkGoDaddyAndCheckEmail(email) {
29
+ hide('#godaddy_block');
30
+ hide('#godaddy_spf_required');
31
+ // are we hosted on GoDaddy? check.
32
+ var data = {
33
+ 'action' : 'postman_wizard_port_test',
34
+ 'hostname' : 'relay-hosting.secureserver.net',
35
+ 'port' : 25,
36
+ 'timeout' : 3,
37
+ 'security' : jQuery('#security').val(),
38
+ };
39
+ goDaddy = 'unknown';
40
+ checkedEmail = false;
41
+ jQuery.post(ajaxurl, data, function(response) {
42
+ if (postmanValidateAjaxResponseWithPopup(response)) {
43
+ checkEmail(response.success, email);
44
+ }
45
+ }).fail(function(response) {
46
+ ajaxFailed(response);
47
+ });
48
+ }
49
+
50
+ function checkEmail(goDaddyHostDetected, email) {
51
+ var data = {
52
+ 'action' : 'postman_check_email',
53
+ 'go_daddy' : goDaddyHostDetected,
54
+ 'email' : email,
55
+ 'security' : jQuery('#security').val()
56
+ };
57
+ jQuery.post(
58
+ ajaxurl,
59
+ data,
60
+ function(response) {
61
+ if (postmanValidateAjaxResponseWithPopup(response)) {
62
+ checkedEmail = true;
63
+ smtpDiscovery = response.data;
64
+ if (response.data.hostname != null
65
+ && response.data.hostname) {
66
+ jQuery(post_smtp_localize.postman_hostname_element_name).val(
67
+ response.data.hostname);
68
+ }
69
+ enableSmtpHostnameInput(goDaddyHostDetected);
70
+ }
71
+ }).fail(function(response) {
72
+ ajaxFailed(response);
73
+ });
74
+ }
75
+
76
+ function enableSmtpHostnameInput(goDaddyHostDetected) {
77
+ if (goDaddyHostDetected && !smtpDiscovery.is_google) {
78
+ // this is a godaddy server and we are using a godaddy smtp server
79
+ // (gmail excepted)
80
+ if (smtpDiscovery.is_go_daddy) {
81
+ // we detected GoDaddy, and the user has entered a GoDaddy hosted
82
+ // email
83
+ } else if (smtpDiscovery.is_well_known) {
84
+ // this is a godaddy server but the SMTP must be the email
85
+ // service
86
+ show('#godaddy_block');
87
+ } else {
88
+ // this is a godaddy server and we're using a (possibly) custom
89
+ // domain
90
+ show('#godaddy_spf_required');
91
+ }
92
+ }
93
+ enable('#input_hostname');
94
+ jQuery('li').removeClass('disabled');
95
+ hideLoaderIcon();
96
+ }
97
+
98
+ /**
99
+ * Initialize the Steps wizard
100
+ */
101
+ function initializeJQuerySteps() {
102
+ jQuery("#postman_wizard").steps(
103
+ {
104
+ bodyTag : "fieldset",
105
+ headerTag : "h5",
106
+ transitionEffect : "slideLeft",
107
+ stepsOrientation : "vertical",
108
+ autoFocus : true,
109
+ startIndex : parseInt(postman_setup_wizard.start_page),
110
+ labels : {
111
+ current : post_smtp_localize.steps_current_step,
112
+ pagination : post_smtp_localize.steps_pagination,
113
+ finish : post_smtp_localize.steps_finish,
114
+ next : post_smtp_localize.steps_next,
115
+ previous : post_smtp_localize.steps_previous,
116
+ loading : post_smtp_localize.steps_loading
117
+ },
118
+ onStepChanging : function(event, currentIndex, newIndex) {
119
+
120
+ var response = handleStepChange( event, currentIndex, newIndex, jQuery( this ) );
121
+
122
+ if( response ) {
123
+
124
+ if( !jQuery( `#postman_wizard-t-${currentIndex} span` ).hasClass( 'dashicons' ) )
125
+ jQuery( `#postman_wizard-t-${currentIndex}` ).append( '<span class="ps-right dashicons dashicons-yes-alt"></span>' );
126
+
127
+ }
128
+
129
+ return response;
130
+
131
+ },
132
+ onInit : function() {
133
+
134
+ if( !jQuery( `#postman_wizard-t-0 span` ).hasClass( 'dashicons' ) )
135
+ jQuery( '#postman_wizard-t-0' ).append( '<span class="ps-right dashicons dashicons-yes-alt"></span>' );
136
+
137
+ jQuery(post_smtp_localize.postman_input_sender_email).focus();
138
+
139
+ },
140
+ onStepChanged : function(event, currentIndex, priorIndex) {
141
+ return postHandleStepChange(event, currentIndex,
142
+ priorIndex, jQuery(this));
143
+ },
144
+ onFinishing : function(event, currentIndex) {
145
+ var form = jQuery(this);
146
+
147
+ // Disable validation on fields that
148
+ // are disabled.
149
+ // At this point it's recommended to
150
+ // do an overall check (mean
151
+ // ignoring
152
+ // only disabled fields)
153
+ // form.validate().settings.ignore =
154
+ // ":disabled";
155
+
156
+ // Start validation; Prevent form
157
+ // submission if false
158
+ return form.valid();
159
+ },
160
+ onFinished : function(event, currentIndex) {
161
+ var form = jQuery(this);
162
+
163
+ // Submit form input
164
+ form.submit();
165
+ }
166
+ }).validate({
167
+ errorPlacement : function(error, element) {
168
+ element.before(error);
169
+ }
170
+ });
171
+ }
172
+
173
+ function handleStepChange(event, currentIndex, newIndex, form) {
174
+ // Always allow going backward even if
175
+ // the current step contains invalid fields!
176
+ if (currentIndex > newIndex) {
177
+ if (currentIndex === 2 && !(checkedEmail)) {
178
+ return false;
179
+ }
180
+ if (currentIndex === 3 && portTestInProgress) {
181
+ return false;
182
+ }
183
+ return true;
184
+ }
185
+
186
+ // Clean up if user went backward
187
+ // before
188
+ if (currentIndex < newIndex) {
189
+ // To remove error styles
190
+ jQuery(".body:eq(" + newIndex + ") label.error", form).remove();
191
+ jQuery(".body:eq(" + newIndex + ") .error", form).removeClass("error");
192
+ }
193
+
194
+ // Disable validation on fields that
195
+ // are disabled or hidden.
196
+ form.validate().settings.ignore = ":disabled,:hidden";
197
+
198
+ // Start validation; Prevent going
199
+ // forward if false
200
+ valid = form.valid();
201
+ if (!valid) {
202
+ return false;
203
+ }
204
+
205
+ if (currentIndex === 1) {
206
+ // page 1 : look-up the email
207
+ // address for the smtp server
208
+ checkGoDaddyAndCheckEmail(jQuery(post_smtp_localize.postman_input_sender_email).val());
209
+
210
+ } else if (currentIndex === 2) {
211
+
212
+ if (!(checkedEmail)) {
213
+ return false;
214
+ }
215
+ // page 2 : check the port
216
+ portsChecked = 0;
217
+ portsToCheck = 0;
218
+ totalAvail = 0;
219
+
220
+ getHostsToCheck(jQuery(post_smtp_localize.postman_hostname_element_name).val());
221
+
222
+ } else if (currentIndex === 3) {
223
+
224
+ // user has clicked next but we haven't finished the check
225
+ if (portTestInProgress) {
226
+ return false;
227
+ }
228
+ // or all ports are unavailable
229
+ if (portCheckBlocksUi) {
230
+ return false;
231
+ }
232
+ valid = form.valid();
233
+ if (!valid) {
234
+ return false;
235
+ }
236
+ var chosenPort = jQuery(post_smtp_localize.postman_port_element_name).val();
237
+ var hostname = jQuery(post_smtp_localize.postman_hostname_element_name).val();
238
+ var authType = jQuery(post_smtp_localize.postman_input_auth_type).val()
239
+
240
+ }
241
+
242
+ return true;
243
+ }
244
+
245
+ function postHandleStepChange(event, currentIndex, priorIndex, myself) {
246
+ var chosenPort = jQuery('#input_auth_type').val();
247
+ // Suppress (skip) "Warning" step if
248
+ // the user is old enough and wants
249
+ // to the previous step.
250
+ if (currentIndex === 2) {
251
+ jQuery(post_smtp_localize.postman_hostname_element_name).focus();
252
+ // this is the second place i disable the next button but Steps
253
+ // re-enables it after the screen slides
254
+ if (priorIndex === 1) {
255
+ disable('#input_hostname');
256
+ jQuery('li').addClass('disabled');
257
+ showLoaderIcon();
258
+ }
259
+ }
260
+ if (currentIndex === 3) {
261
+ if (priorIndex === 2) {
262
+ // this is the second place i disable the next button but Steps
263
+ // re-enables it after the screen slides
264
+ jQuery('li').addClass('disabled');
265
+ showLoaderIcon();
266
+ }
267
+ }
268
+ if (currentIndex === 4) {
269
+ if (redirectUrlWarning) {
270
+ alert(post_smtp_localize.postman_wizard_bad_redirect_url);
271
+ }
272
+ if (chosenPort == 'none') {
273
+ if (priorIndex === 5) {
274
+
275
+ myself.steps("previous");
276
+ return;
277
+ }
278
+ myself.steps("next");
279
+ }
280
+ }
281
+
282
+ }
283
+
284
+ /**
285
+ * Asks the server for a List of sockets to perform port checks upon.
286
+ *
287
+ * @param hostname
288
+ */
289
+ function getHostsToCheck(hostname) {
290
+ jQuery('table#wizard_port_test').html('');
291
+ jQuery('#wizard_recommendation').html('');
292
+ hide('.user_override');
293
+ hide('#smtp_not_secure');
294
+ hide('#smtp_mitm');
295
+ connectivtyTestResults = {};
296
+ portCheckBlocksUi = true;
297
+ portTestInProgress = true;
298
+ var data = {
299
+ 'action' : 'postman_get_hosts_to_test',
300
+ 'hostname' : hostname,
301
+ 'original_smtp_server' : smtpDiscovery.hostname,
302
+ 'security' : jQuery('#security').val(),
303
+ };
304
+ jQuery.post(ajaxurl, data, function(response) {
305
+ if (postmanValidateAjaxResponseWithPopup(response)) {
306
+ handleHostsToCheckResponse(response.data);
307
+ }
308
+ }).fail(function(response) {
309
+ ajaxFailed(response);
310
+ });
311
+ }
312
+
313
+ /**
314
+ * Handles the response from the server of the list of sockets to check.
315
+ *
316
+ * @param hostname
317
+ * @param response
318
+ */
319
+ function handleHostsToCheckResponse(response) {
320
+ for ( var x in response.hosts) {
321
+ var hostname = response.hosts[x].host;
322
+ var port = response.hosts[x].port;
323
+ var transport = response.hosts[x].transport_id;
324
+ var logoURL = response.hosts[x].logo_url;
325
+ portsToCheck++;
326
+ show('#connectivity_test_status');
327
+ updateStatus(postman_port_test.in_progress + " " + portsToCheck);
328
+ var data = {
329
+ 'action' : 'postman_wizard_port_test',
330
+ 'hostname' : hostname,
331
+ 'port' : port,
332
+ 'transport' : transport,
333
+ 'logo_url': logoURL,
334
+ 'security' : jQuery('#security').val(),
335
+ };
336
+ postThePortTest(hostname, port, data);
337
+ }
338
+ }
339
+
340
+ /**
341
+ * Asks the server to run a connectivity test on the given port
342
+ *
343
+ * @param hostname
344
+ * @param port
345
+ * @param data
346
+ */
347
+ function postThePortTest(hostname, port, data) {
348
+ jQuery.post(ajaxurl, data, function(response) {
349
+ if (postmanValidateAjaxResponseWithPopup(response)) {
350
+ handlePortTestResponse(hostname, port, data, response);
351
+ }
352
+ }).fail(function(response) {
353
+ ajaxFailed(response);
354
+ portsChecked++;
355
+ afterPortsChecked();
356
+ });
357
+ }
358
+
359
+ /**
360
+ * Handles the result of the port test
361
+ *
362
+ * @param hostname
363
+ * @param port
364
+ * @param data
365
+ * @param response
366
+ */
367
+ function handlePortTestResponse(hostname, port, data, response) {
368
+ if (!response.data.try_smtps) {
369
+ portsChecked++;
370
+ updateStatus(postman_port_test.in_progress + " "
371
+ + (portsToCheck - portsChecked));
372
+ connectivtyTestResults[hostname + '_' + port] = response.data;
373
+ if (response.success) {
374
+ // a totalAvail > 0 is our signal to go to the next step
375
+ totalAvail++;
376
+ }
377
+ afterPortsChecked();
378
+ } else {
379
+ // SMTP failed, try again on the SMTPS port
380
+ data['action'] = 'postman_wizard_port_test_smtps';
381
+ data['security'] = jQuery('#security').val();
382
+ postThePortTest(hostname, port, data);
383
+ }
384
+ }
385
+
386
+ /**
387
+ *
388
+ * @param message
389
+ */
390
+ function updateStatus(message) {
391
+ jQuery('#port_test_status').html(
392
+ '<span style="color:blue">' + message + '</span>');
393
+ }
394
+
395
+ /**
396
+ * This functions runs after ALL the ports have been checked. It's chief
397
+ * function is to push the results of the port test back to the server to get a
398
+ * suggested configuration.
399
+ */
400
+ function afterPortsChecked() {
401
+ if (portsChecked >= portsToCheck) {
402
+ hideLoaderIcon();
403
+ if (totalAvail != 0) {
404
+ jQuery('li').removeClass('disabled');
405
+ portCheckBlocksUi = false;
406
+ }
407
+ var data = {
408
+ 'action' : 'get_wizard_configuration_options',
409
+ 'original_smtp_server' : smtpDiscovery.hostname,
410
+ 'host_data' : connectivtyTestResults,
411
+ 'security': jQuery('#security').val()
412
+ };
413
+ postTheConfigurationRequest(data);
414
+ hide('#connectivity_test_status');
415
+ }
416
+ }
417
+
418
+ function userOverrideMenu() {
419
+ disable('input.user_socket_override');
420
+ disable('input.user_auth_override');
421
+ var data = {
422
+ 'action' : 'get_wizard_configuration_options',
423
+ 'original_smtp_server' : smtpDiscovery.hostname,
424
+ 'user_port_override' : jQuery(
425
+ "input:radio[name='user_socket_override']:checked").val(),
426
+ 'user_auth_override' : jQuery(
427
+ "input:radio[name='user_auth_override']:checked").val(),
428
+ 'host_data' : connectivtyTestResults,
429
+ 'security' : jQuery('#security').val()
430
+ };
431
+ postTheConfigurationRequest(data);
432
+ }
433
+
434
+ function postTheConfigurationRequest(data) {
435
+ jQuery.post(
436
+ ajaxurl,
437
+ data,
438
+ function(response) {
439
+ if (postmanValidateAjaxResponseWithPopup(response)) {
440
+ portTestInProgress = false;
441
+ var $message = '';
442
+ if (response.success) {
443
+ $message = '<span style="color:green">'
444
+ + response.data.configuration.message
445
+ + '</span>';
446
+ handleConfigurationResponse(response.data);
447
+ enable('input.user_socket_override');
448
+ enable('input.user_auth_override');
449
+ // enable both next/back buttons
450
+ jQuery('li').removeClass('disabled');
451
+ } else {
452
+ $message = '<span style="color:red">'
453
+ + response.data.configuration.message
454
+ + '</span>';
455
+ // enable the back button only
456
+ jQuery('li').removeClass('disabled');
457
+ jQuery('li + li').addClass('disabled');
458
+ }
459
+ if (!response.data.configuration.user_override) {
460
+ jQuery('#wizard_recommendation').append($message);
461
+ }
462
+ }
463
+ }).fail(function(response) {
464
+ ajaxFailed(response);
465
+ });
466
+ }
467
+ function handleConfigurationResponse(response) {
468
+
469
+ var html = '';
470
+ var authHtml = '';
471
+
472
+ jQuery('#input_transport_type').val(response.configuration.transport_type);
473
+ transports.forEach(function(item) {
474
+ item.handleConfigurationResponse(response);
475
+ })
476
+
477
+ // this stuff builds the options and is common to all transports
478
+ // populate user Port Override menu
479
+ show('.user_override');
480
+ var el1 = jQuery('#user_socket_override');
481
+ el1.html('');
482
+
483
+ var columns = 1;
484
+
485
+ for (i = 0; i < response.override_menu.length; i++) {
486
+
487
+ response.override_menu[i].data = response.override_menu[i].data !== null ? response.override_menu[i].data : false;
488
+
489
+ if( columns == 1 ) {
490
+ html += "<div class='ps-socket-wizad-row'>";
491
+ }
492
+
493
+ html += buildRadioButtonGroup(
494
+ 'user_socket_override',
495
+ response.override_menu[i].selected,
496
+ response.override_menu[i].value,
497
+ response.override_menu[i].description,
498
+ response.override_menu[i].secure,
499
+ response.override_menu[i].data
500
+ );
501
+
502
+ if( columns == 3 ) {
503
+ html += '</div>';
504
+ columns = 0;
505
+ }
506
+
507
+ columns++;
508
+
509
+ // populate user Auth Override menu
510
+ if (response.override_menu[i].selected) {
511
+ if (response.override_menu[i].mitm) {
512
+ show('#smtp_mitm');
513
+ jQuery('#smtp_mitm')
514
+ .html(
515
+ sprintf(
516
+ postman_port_test.mitm,
517
+ response.override_menu[i].reported_hostname_domain_only,
518
+ response.override_menu[i].hostname_domain_only));
519
+ } else {
520
+ hide('#smtp_mitm');
521
+ }
522
+ var el2 = jQuery('#user_auth_override');
523
+ el2.html('');
524
+ hide('#smtp_not_secure');
525
+ for (j = 0; j < response.override_menu[i].auth_items.length; j++) {
526
+
527
+ authHtml += buildRadioButtonGroup(
528
+ 'user_auth_override',
529
+ response.override_menu[i].auth_items[j].selected,
530
+ response.override_menu[i].auth_items[j].value,
531
+ response.override_menu[i].auth_items[j].name,
532
+ false
533
+ );
534
+
535
+ if (response.override_menu[i].auth_items[j].selected
536
+ && !response.override_menu[i].secure
537
+ && response.override_menu[i].auth_items[j].value != 'none') {
538
+ show('#smtp_not_secure');
539
+ }
540
+ }
541
+ }
542
+
543
+
544
+ }
545
+
546
+ el1.append( html );
547
+ el2.append( authHtml );
548
+
549
+ jQuery.fn.suggestPro();
550
+
551
+ jQuery('select#input_notification_service').change(function() {
552
+ var selected = jQuery( this ).val();
553
+
554
+ if ( selected == 'default' ) {
555
+ jQuery('#slack_cred').fadeOut('fast');
556
+ jQuery('#pushover_cred').fadeOut('fast');
557
+ }
558
+
559
+ if ( selected == 'pushover' ) {
560
+ jQuery('#slack_cred').fadeOut('fast');
561
+ jQuery('#pushover_cred').fadeIn();
562
+ }
563
+
564
+ if ( selected == 'slack' ) {
565
+ jQuery('#pushover_cred').fadeOut('fast');
566
+ jQuery('#slack_cred').fadeIn();
567
+ }
568
+
569
+ Hook.call( 'post_smtp_notification_change', selected );
570
+ });
571
+
572
+ // Add an event on Socket Selection/ Switching
573
+ jQuery( 'input.user_socket_override' ).change( function() {
574
+ userOverrideMenu();
575
+ } );
576
+
577
+ // Add an event on Socket's Auth Type Selection/ Switching
578
+ jQuery( 'input.user_auth_override' ).change( function() {
579
+ userOverrideMenu();
580
+ } );
581
+ }
582
+
583
+ /**
584
+ *
585
+ * @param {*} radioGroupName
586
+ * @param {*} isSelected
587
+ * @param {*} value
588
+ * @param {*} label
589
+ * @param {*} isSecure
590
+ * @param {*} data
591
+ * @returns
592
+ *
593
+ * @since 2.1 Returns html instead of appending
594
+ */
595
+ function buildRadioButtonGroup( radioGroupName, isSelected, value, label, isSecure, data = '' ) {
596
+
597
+ var radioInputValue = ' value="' + value + '"';
598
+ var radioInputChecked = '';
599
+ var secureIcon = '';
600
+ var logoTag = '';
601
+ var html = '';
602
+ var recommendedBlock = '';
603
+ var relativeClass = '';
604
+
605
+ if (isSelected) {
606
+ radioInputChecked = ' checked = "checked"';
607
+ }
608
+
609
+ if (isSecure) {
610
+ secureIcon = '&#x1f512;';
611
+ }
612
+
613
+ if( data.logo_url && data.logo_url !== undefined ) {
614
+
615
+ if( label == 'Sendinblue' ) {
616
+
617
+ relativeClass = 'ps-sib';
618
+ recommendedBlock = `
619
+ <img src="${postman.assets}images/icons/recommended.png" class="ps-sib-recommended" />
620
+ `;
621
+
622
+ }
623
+
624
+ logoTag = `
625
+ <div class='ps-single-socket-outer ${relativeClass}'>
626
+ ${recommendedBlock}
627
+ <img src='${data.logo_url}' class='ps-wizard-socket-logo' width='165px' />
628
+ </div>
629
+ `;
630
+
631
+ }
632
+
633
+ html = `
634
+ <label>
635
+ ${logoTag}
636
+ <input class="${radioGroupName}" type="radio" name="${radioGroupName}"${radioInputChecked} ${radioInputValue} />
637
+ ${secureIcon + label}
638
+ </label>
639
+ `;
640
+
641
+ return html;
642
+
643
+ }
644
+
645
+ /**
646
+ * Handles population of the configuration based on the options set in a
647
+ * 3rd-party SMTP plugin
648
+ */
649
+ function getConfiguration() {
650
+ var plugin = jQuery('input[name="input_plugin"]' + ':checked').val();
651
+ if (plugin != '') {
652
+ var data = {
653
+ 'action' : 'import_configuration',
654
+ 'plugin' : plugin,
655
+ 'security' : jQuery('#security').val(),
656
+ };
657
+ jQuery
658
+ .post(
659
+ ajaxurl,
660
+ data,
661
+ function(response) {
662
+ if (response.success) {
663
+ jQuery('select#input_transport_type').val(
664
+ 'smtp');
665
+ jQuery(post_smtp_localize.postman_input_sender_email).val(
666
+ response.sender_email);
667
+ jQuery(post_smtp_localize.postman_input_sender_name).val(
668
+ response.sender_name);
669
+ jQuery(post_smtp_localize.postman_hostname_element_name).val(
670
+ response.hostname);
671
+ jQuery(post_smtp_localize.postman_port_element_name).val(
672
+ response.port);
673
+ jQuery(post_smtp_localize.postman_input_auth_type).val(
674
+ response.auth_type);
675
+ jQuery('#input_enc_type')
676
+ .val(response.enc_type);
677
+ jQuery(post_smtp_localize.postman_input_basic_username).val(
678
+ response.basic_auth_username);
679
+ jQuery(post_smtp_localize.postman_input_basic_password).val(
680
+ response.basic_auth_password);
681
+ switchBetweenPasswordAndOAuth();
682
+ }
683
+ }).fail(function(response) {
684
+ ajaxFailed(response);
685
+ });
686
+ } else {
687
+ jQuery(post_smtp_localize.postman_input_sender_email).val('');
688
+ jQuery(post_smtp_localize.postman_input_sender_name).val('');
689
+ jQuery(post_smtp_localize.postman_input_basic_username).val('');
690
+ jQuery(post_smtp_localize.postman_input_basic_password).val('');
691
+ jQuery(post_smtp_localize.postman_hostname_element_name).val('');
692
+ jQuery(post_smtp_localize.postman_port_element_name).val('');
693
+ jQuery(post_smtp_localize.postman_input_auth_type).val('none');
694
+ jQuery(post_smtp_localize.postman_enc_for_password_el).val('none');
695
+ switchBetweenPasswordAndOAuth();
696
+ }
697
+ }
Postman/Postman-Connectivity-Test/Postman-PortTest.php CHANGED
@@ -1,286 +1,286 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- require_once ("registered-domain-libs-master/PHP/effectiveTLDs.inc.php");
7
- require_once ("registered-domain-libs-master/PHP/regDomain.inc.php");
8
-
9
- /**
10
- *
11
- * @author jasonhendriks
12
- *
13
- */
14
- class PostmanPortTest {
15
- private $errstr;
16
- private $logger;
17
- private $hostname;
18
- public $hostnameDomainOnly;
19
- private $port;
20
- private $connectionTimeout;
21
- private $readTimeout;
22
- public $reportedHostname;
23
- public $reportedHostnameDomainOnly;
24
- public $protocol;
25
- public $secure;
26
- public $mitm;
27
- public $http;
28
- public $https;
29
- public $smtp;
30
- public $smtps;
31
- public $startTls;
32
- public $checkStartTls;
33
- public $authLogin;
34
- public $authPlain;
35
- public $authCrammd5;
36
- public $authXoauth;
37
- public $authNone;
38
- public $trySmtps;
39
-
40
- //
41
- const SMTPS_PROTOCOL = 'SMTPS';
42
-
43
- /**
44
- */
45
- public function __construct($hostname, $port) {
46
- $this->logger = new PostmanLogger ( get_class ( $this ) );
47
- $this->hostname = $hostname;
48
- $this->hostnameDomainOnly = $this->getRegisteredDomain ( $hostname );
49
- $this->port = $port;
50
- $this->connectionTimeout = 10;
51
- $this->readTimeout = 10;
52
- }
53
-
54
- /**
55
- * Wrap the regDomain/getRegisteredDomain function
56
- *
57
- * @param mixed $domain
58
- * @return mixed
59
- */
60
- private function getRegisteredDomain($hostname) {
61
- $registeredDomain = getRegisteredDomain ( $hostname );
62
- if ($registeredDomain === NULL) {
63
- return $hostname;
64
- }
65
- return $registeredDomain;
66
- }
67
- public function setConnectionTimeout($timeout) {
68
- $this->connectionTimeout = $timeout;
69
- $this->logger->trace ( $this->connectionTimeout );
70
- }
71
- public function setReadTimeout($timeout) {
72
- $this->readTimeout = $timeout;
73
- $this->logger->trace ( $this->readTimeout );
74
- }
75
- private function createStream($connectionString) {
76
- $stream = @stream_socket_client ( $connectionString, $errno, $errstr, $this->connectionTimeout );
77
- if ($stream) {
78
- $this->trace ( sprintf ( 'connected to %s', $connectionString ) );
79
- } else {
80
- $this->trace ( sprintf ( 'Could not connect to %s because %s [%s]', $connectionString, $errstr, $errno ) );
81
- }
82
- return $stream;
83
- }
84
-
85
- /**
86
- *
87
- * @param number $timeout
88
- * @return boolean
89
- */
90
- public function genericConnectionTest() {
91
- $this->logger->trace ( 'testCustomConnection()' );
92
- // test if the port is open
93
- $connectionString = sprintf ( '%s:%s', $this->hostname, $this->port );
94
- $stream = $this->createStream ( $connectionString, $this->connectionTimeout );
95
- return null != $stream;
96
- }
97
-
98
- /**
99
- * Given a hostname, test if it has open ports
100
- *
101
- * @param string $hostname
102
- */
103
- public function testHttpPorts() {
104
- $this->trace ( 'testHttpPorts()' );
105
- $connectionString = sprintf ( "https://%s:%s", $this->hostname, $this->port );
106
- try {
107
- $response = PostmanUtils::remotePost ( $connectionString );
108
- $this->trace ( 'wp_remote_retrieve_headers:' );
109
- $this->logger->trace ( wp_remote_retrieve_headers ( $response ) );
110
- $this->trace ( wp_remote_retrieve_response_code ( $response ) );
111
- $this->protocol = 'HTTPS';
112
- $this->http = true;
113
- $this->https = true;
114
- $this->secure = true;
115
- $this->reportedHostname = $this->hostname;
116
- $this->reportedHostnameDomainOnly = $this->getRegisteredDomain ( $this->hostname );
117
- return true;
118
- } catch ( Exception $e ) {
119
- $this->debug ( 'return false' );
120
- }
121
- }
122
-
123
- /**
124
- * Given a hostname, test if it has open ports
125
- *
126
- * @param string $hostname
127
- */
128
- public function testSmtpPorts() {
129
- $this->logger->trace ( 'testSmtpPorts()' );
130
- if ($this->port == 8025) {
131
- $this->debug ( 'Executing test code for port 8025' );
132
- $this->protocol = 'SMTP';
133
- $this->smtp = true;
134
- $this->authNone = 'true';
135
- return true;
136
- }
137
- $connectionString = sprintf ( "%s:%s", $this->hostname, $this->port );
138
- $success = $this->talkToMailServer ( $connectionString, $this->connectionTimeout, $this->readTimeout );
139
- if ($success) {
140
- $this->protocol = 'SMTP';
141
- if (! ($this->authCrammd5 || $this->authLogin || $this->authPlain || $this->authXoauth)) {
142
- $this->authNone = true;
143
- }
144
- } else {
145
- $this->trySmtps = true;
146
- }
147
- return $success;
148
- }
149
-
150
- /**
151
- * Given a hostname, test if it has open ports
152
- *
153
- * @param string $hostname
154
- */
155
- public function testSmtpsPorts() {
156
- $this->logger->trace ( 'testSmtpsPorts()' );
157
- $connectionString = sprintf ( "ssl://%s:%s", $this->hostname, $this->port );
158
- $success = $this->talkToMailServer ( $connectionString, $this->connectionTimeout, $this->readTimeout );
159
- if ($success) {
160
- if (! ($this->authCrammd5 || $this->authLogin || $this->authPlain || $this->authXoauth)) {
161
- $this->authNone = true;
162
- }
163
- $this->protocol = self::SMTPS_PROTOCOL;
164
- $this->smtps = true;
165
- $this->secure = true;
166
- }
167
- return $success;
168
- }
169
-
170
- /**
171
- * Given a hostname, test if it has open ports
172
- *
173
- * @param string $hostname
174
- */
175
- private function talkToMailServer($connectionString) {
176
- $this->logger->trace ( 'talkToMailServer()' );
177
- $stream = $this->createStream ( $connectionString, $this->connectionTimeout );
178
- if ($stream) {
179
- $serverName = PostmanUtils::postmanGetServerName ();
180
- @stream_set_timeout ( $stream, $this->readTimeout );
181
- // see http://php.net/manual/en/transports.inet.php#113244
182
- // see http://php.net/stream_socket_enable_crypto
183
- $result = $this->readSmtpResponse ( $stream );
184
- if ($result) {
185
- $this->reportedHostname = $result;
186
- $this->reportedHostnameDomainOnly = $this->getRegisteredDomain ( $this->reportedHostname );
187
- $this->logger->trace ( sprintf ( 'comparing %s with %s', $this->reportedHostnameDomainOnly, $this->hostnameDomainOnly ) );
188
- $this->mitm = true;
189
- // MITM exceptions
190
- if ($this->reportedHostnameDomainOnly == 'google.com' && $this->hostnameDomainOnly == 'gmail.com') {
191
- $this->mitm = false;
192
- } elseif ($this->reportedHostnameDomainOnly == 'hotmail.com' && $this->hostnameDomainOnly == 'live.com') {
193
- $this->mitm = false;
194
- } elseif ($this->reportedHostnameDomainOnly == $this->hostnameDomainOnly) {
195
- $this->mitm = false;
196
- }
197
- $this->debug ( sprintf ( 'domain name: %s (%s)', $this->reportedHostname, $this->reportedHostnameDomainOnly ) );
198
- $this->sendSmtpCommand ( $stream, sprintf ( 'EHLO %s', $serverName ) );
199
- $this->readSmtpResponse ( $stream );
200
- if ($this->checkStartTls) {
201
- $this->sendSmtpCommand ( $stream, 'STARTTLS' );
202
- $this->readSmtpResponse ( $stream );
203
- $starttlsSuccess = @stream_socket_enable_crypto ( $stream, true, STREAM_CRYPTO_METHOD_TLS_CLIENT );
204
- if ($starttlsSuccess) {
205
- $this->startTls = true;
206
- $this->secure = true;
207
- $this->sendSmtpCommand ( $stream, sprintf ( 'EHLO %s', $serverName ) );
208
- $this->readSmtpResponse ( $stream );
209
- } else {
210
- $this->error ( 'starttls failed' );
211
- }
212
- }
213
- fclose ( $stream );
214
- $this->debug ( 'return true' );
215
- return true;
216
- } else {
217
- fclose ( $stream );
218
- $this->debug ( 'return false' );
219
- return false;
220
- }
221
- } else {
222
- return false;
223
- }
224
- }
225
- private function sendSmtpCommand($stream, $message) {
226
- $this->trace ( 'tx: ' . $message );
227
- fputs ( $stream, $message . "\r\n" );
228
- }
229
- private function readSmtpResponse($stream) {
230
- $result = '';
231
- while ( ($line = fgets ( $stream )) !== false ) {
232
- $this->trace ( 'rx: ' . $line );
233
- if (preg_match ( '/^250.AUTH/', $line )) {
234
- // $this->debug ( '250-AUTH' );
235
- if (preg_match ( '/\\sLOGIN\\s/', $line )) {
236
- $this->authLogin = true;
237
- $this->debug ( 'authLogin' );
238
- }
239
- if (preg_match ( '/\\sPLAIN\\s/', $line )) {
240
- $this->authPlain = true;
241
- $this->debug ( 'authPlain' );
242
- }
243
- if (preg_match ( '/\\sCRAM-MD5\\s/', $line )) {
244
- $this->authCrammd5 = true;
245
- $this->debug ( 'authCrammd5' );
246
- }
247
- if (preg_match ( '/\\sXOAUTH.\\s/', $line )) {
248
- $this->authXoauth = true;
249
- $this->debug ( 'authXoauth' );
250
- }
251
- if (preg_match ( '/\\sANONYMOUS\\s/', $line )) {
252
- // Postman treats ANONYMOUS login as no authentication.
253
- $this->authNone = true;
254
- $this->debug ( 'authAnonymous => authNone' );
255
- }
256
- // done
257
- $result = 'auth';
258
- } elseif (preg_match ( '/STARTTLS/', $line )) {
259
- $result = 'starttls';
260
- $this->checkStartTls = true;
261
- $this->debug ( 'starttls' );
262
- } elseif (preg_match ( '/^220.(.*?)\\s/', $line, $matches )) {
263
- if (empty ( $result ))
264
- $result = $matches [1];
265
- }
266
- if (preg_match ( '/^\d\d\d\\s/', $line )) {
267
- // always exist on last server response line
268
- // $this->debug ( 'exit' );
269
- return $result;
270
- }
271
- }
272
- return false;
273
- }
274
- public function getErrorMessage() {
275
- return $this->errstr;
276
- }
277
- private function trace($message) {
278
- $this->logger->trace ( sprintf ( '%s:%s => %s', $this->hostname, $this->port, $message ) );
279
- }
280
- private function debug($message) {
281
- $this->logger->debug ( sprintf ( '%s:%s => %s', $this->hostname, $this->port, $message ) );
282
- }
283
- private function error($message) {
284
- $this->logger->error ( sprintf ( '%s:%s => %s', $this->hostname, $this->port, $message ) );
285
- }
286
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ require_once ("registered-domain-libs-master/PHP/effectiveTLDs.inc.php");
7
+ require_once ("registered-domain-libs-master/PHP/regDomain.inc.php");
8
+
9
+ /**
10
+ *
11
+ * @author jasonhendriks
12
+ *
13
+ */
14
+ class PostmanPortTest {
15
+ private $errstr;
16
+ private $logger;
17
+ private $hostname;
18
+ public $hostnameDomainOnly;
19
+ private $port;
20
+ private $connectionTimeout;
21
+ private $readTimeout;
22
+ public $reportedHostname;
23
+ public $reportedHostnameDomainOnly;
24
+ public $protocol;
25
+ public $secure;
26
+ public $mitm;
27
+ public $http;
28
+ public $https;
29
+ public $smtp;
30
+ public $smtps;
31
+ public $startTls;
32
+ public $checkStartTls;
33
+ public $authLogin;
34
+ public $authPlain;
35
+ public $authCrammd5;
36
+ public $authXoauth;
37
+ public $authNone;
38
+ public $trySmtps;
39
+
40
+ //
41
+ const SMTPS_PROTOCOL = 'SMTPS';
42
+
43
+ /**
44
+ */
45
+ public function __construct($hostname, $port) {
46
+ $this->logger = new PostmanLogger ( get_class ( $this ) );
47
+ $this->hostname = $hostname;
48
+ $this->hostnameDomainOnly = $this->getRegisteredDomain ( $hostname );
49
+ $this->port = $port;
50
+ $this->connectionTimeout = 10;
51
+ $this->readTimeout = 10;
52
+ }
53
+
54
+ /**
55
+ * Wrap the regDomain/getRegisteredDomain function
56
+ *
57
+ * @param mixed $domain
58
+ * @return mixed
59
+ */
60
+ private function getRegisteredDomain($hostname) {
61
+ $registeredDomain = getRegisteredDomain ( $hostname );
62
+ if ($registeredDomain === NULL) {
63
+ return $hostname;
64
+ }
65
+ return $registeredDomain;
66
+ }
67
+ public function setConnectionTimeout($timeout) {
68
+ $this->connectionTimeout = $timeout;
69
+ $this->logger->trace ( $this->connectionTimeout );
70
+ }
71
+ public function setReadTimeout($timeout) {
72
+ $this->readTimeout = $timeout;
73
+ $this->logger->trace ( $this->readTimeout );
74
+ }
75
+ private function createStream($connectionString) {
76
+ $stream = @stream_socket_client ( $connectionString, $errno, $errstr, $this->connectionTimeout );
77
+ if ($stream) {
78
+ $this->trace ( sprintf ( 'connected to %s', $connectionString ) );
79
+ } else {
80
+ $this->trace ( sprintf ( 'Could not connect to %s because %s [%s]', $connectionString, $errstr, $errno ) );
81
+ }
82
+ return $stream;
83
+ }
84
+
85
+ /**
86
+ *
87
+ * @param number $timeout
88
+ * @return boolean
89
+ */
90
+ public function genericConnectionTest() {
91
+ $this->logger->trace ( 'testCustomConnection()' );
92
+ // test if the port is open
93
+ $connectionString = sprintf ( '%s:%s', $this->hostname, $this->port );
94
+ $stream = $this->createStream ( $connectionString, $this->connectionTimeout );
95
+ return null != $stream;
96
+ }
97
+
98
+ /**
99
+ * Given a hostname, test if it has open ports
100
+ *
101
+ * @param string $hostname
102
+ */
103
+ public function testHttpPorts() {
104
+ $this->trace ( 'testHttpPorts()' );
105
+ $connectionString = sprintf ( "https://%s:%s", $this->hostname, $this->port );
106
+ try {
107
+ $response = PostmanUtils::remotePost ( $connectionString );
108
+ $this->trace ( 'wp_remote_retrieve_headers:' );
109
+ $this->logger->trace ( wp_remote_retrieve_headers ( $response ) );
110
+ $this->trace ( wp_remote_retrieve_response_code ( $response ) );
111
+ $this->protocol = 'HTTPS';
112
+ $this->http = true;
113
+ $this->https = true;
114
+ $this->secure = true;
115
+ $this->reportedHostname = $this->hostname;
116
+ $this->reportedHostnameDomainOnly = $this->getRegisteredDomain ( $this->hostname );
117
+ return true;
118
+ } catch ( Exception $e ) {
119
+ $this->debug ( 'return false' );
120
+ }
121
+ }
122
+
123
+ /**
124
+ * Given a hostname, test if it has open ports
125
+ *
126
+ * @param string $hostname
127
+ */
128
+ public function testSmtpPorts() {
129
+ $this->logger->trace ( 'testSmtpPorts()' );
130
+ if ($this->port == 8025) {
131
+ $this->debug ( 'Executing test code for port 8025' );
132
+ $this->protocol = 'SMTP';
133
+ $this->smtp = true;
134
+ $this->authNone = 'true';
135
+ return true;
136
+ }
137
+ $connectionString = sprintf ( "%s:%s", $this->hostname, $this->port );
138
+ $success = $this->talkToMailServer ( $connectionString, $this->connectionTimeout, $this->readTimeout );
139
+ if ($success) {
140
+ $this->protocol = 'SMTP';
141
+ if (! ($this->authCrammd5 || $this->authLogin || $this->authPlain || $this->authXoauth)) {
142
+ $this->authNone = true;
143
+ }
144
+ } else {
145
+ $this->trySmtps = true;
146
+ }
147
+ return $success;
148
+ }
149
+
150
+ /**
151
+ * Given a hostname, test if it has open ports
152
+ *
153
+ * @param string $hostname
154
+ */
155
+ public function testSmtpsPorts() {
156
+ $this->logger->trace ( 'testSmtpsPorts()' );
157
+ $connectionString = sprintf ( "ssl://%s:%s", $this->hostname, $this->port );
158
+ $success = $this->talkToMailServer ( $connectionString, $this->connectionTimeout, $this->readTimeout );
159
+ if ($success) {
160
+ if (! ($this->authCrammd5 || $this->authLogin || $this->authPlain || $this->authXoauth)) {
161
+ $this->authNone = true;
162
+ }
163
+ $this->protocol = self::SMTPS_PROTOCOL;
164
+ $this->smtps = true;
165
+ $this->secure = true;
166
+ }
167
+ return $success;
168
+ }
169
+
170
+ /**
171
+ * Given a hostname, test if it has open ports
172
+ *
173
+ * @param string $hostname
174
+ */
175
+ private function talkToMailServer($connectionString) {
176
+ $this->logger->trace ( 'talkToMailServer()' );
177
+ $stream = $this->createStream ( $connectionString, $this->connectionTimeout );
178
+ if ($stream) {
179
+ $serverName = PostmanUtils::postmanGetServerName ();
180
+ @stream_set_timeout ( $stream, $this->readTimeout );
181
+ // see http://php.net/manual/en/transports.inet.php#113244
182
+ // see http://php.net/stream_socket_enable_crypto
183
+ $result = $this->readSmtpResponse ( $stream );
184
+ if ($result) {
185
+ $this->reportedHostname = $result;
186
+ $this->reportedHostnameDomainOnly = $this->getRegisteredDomain ( $this->reportedHostname );
187
+ $this->logger->trace ( sprintf ( 'comparing %s with %s', $this->reportedHostnameDomainOnly, $this->hostnameDomainOnly ) );
188
+ $this->mitm = true;
189
+ // MITM exceptions
190
+ if ($this->reportedHostnameDomainOnly == 'google.com' && $this->hostnameDomainOnly == 'gmail.com') {
191
+ $this->mitm = false;
192
+ } elseif ($this->reportedHostnameDomainOnly == 'hotmail.com' && $this->hostnameDomainOnly == 'live.com') {
193
+ $this->mitm = false;
194
+ } elseif ($this->reportedHostnameDomainOnly == $this->hostnameDomainOnly) {
195
+ $this->mitm = false;
196
+ }
197
+ $this->debug ( sprintf ( 'domain name: %s (%s)', $this->reportedHostname, $this->reportedHostnameDomainOnly ) );
198
+ $this->sendSmtpCommand ( $stream, sprintf ( 'EHLO %s', $serverName ) );
199
+ $this->readSmtpResponse ( $stream );
200
+ if ($this->checkStartTls) {
201
+ $this->sendSmtpCommand ( $stream, 'STARTTLS' );
202
+ $this->readSmtpResponse ( $stream );
203
+ $starttlsSuccess = @stream_socket_enable_crypto ( $stream, true, STREAM_CRYPTO_METHOD_TLS_CLIENT );
204
+ if ($starttlsSuccess) {
205
+ $this->startTls = true;
206
+ $this->secure = true;
207
+ $this->sendSmtpCommand ( $stream, sprintf ( 'EHLO %s', $serverName ) );
208
+ $this->readSmtpResponse ( $stream );
209
+ } else {
210
+ $this->error ( 'starttls failed' );
211
+ }
212
+ }
213
+ fclose ( $stream );
214
+ $this->debug ( 'return true' );
215
+ return true;
216
+ } else {
217
+ fclose ( $stream );
218
+ $this->debug ( 'return false' );
219
+ return false;
220
+ }
221
+ } else {
222
+ return false;
223
+ }
224
+ }
225
+ private function sendSmtpCommand($stream, $message) {
226
+ $this->trace ( 'tx: ' . $message );
227
+ fputs ( $stream, $message . "\r\n" );
228
+ }
229
+ private function readSmtpResponse($stream) {
230
+ $result = '';
231
+ while ( ($line = fgets ( $stream )) !== false ) {
232
+ $this->trace ( 'rx: ' . $line );
233
+ if (preg_match ( '/^250.AUTH/', $line )) {
234
+ // $this->debug ( '250-AUTH' );
235
+ if (preg_match ( '/\\sLOGIN\\s/', $line )) {
236
+ $this->authLogin = true;
237
+ $this->debug ( 'authLogin' );
238
+ }
239
+ if (preg_match ( '/\\sPLAIN\\s/', $line )) {
240
+ $this->authPlain = true;
241
+ $this->debug ( 'authPlain' );
242
+ }
243
+ if (preg_match ( '/\\sCRAM-MD5\\s/', $line )) {
244
+ $this->authCrammd5 = true;
245
+ $this->debug ( 'authCrammd5' );
246
+ }
247
+ if (preg_match ( '/\\sXOAUTH.\\s/', $line )) {
248
+ $this->authXoauth = true;
249
+ $this->debug ( 'authXoauth' );
250
+ }
251
+ if (preg_match ( '/\\sANONYMOUS\\s/', $line )) {
252
+ // Postman treats ANONYMOUS login as no authentication.
253
+ $this->authNone = true;
254
+ $this->debug ( 'authAnonymous => authNone' );
255
+ }
256
+ // done
257
+ $result = 'auth';
258
+ } elseif (preg_match ( '/STARTTLS/', $line )) {
259
+ $result = 'starttls';
260
+ $this->checkStartTls = true;
261
+ $this->debug ( 'starttls' );
262
+ } elseif (preg_match ( '/^220.(.*?)\\s/', $line, $matches )) {
263
+ if (empty ( $result ))
264
+ $result = $matches [1];
265
+ }
266
+ if (preg_match ( '/^\d\d\d\\s/', $line )) {
267
+ // always exist on last server response line
268
+ // $this->debug ( 'exit' );
269
+ return $result;
270
+ }
271
+ }
272
+ return false;
273
+ }
274
+ public function getErrorMessage() {
275
+ return $this->errstr;
276
+ }
277
+ private function trace($message) {
278
+ $this->logger->trace ( sprintf ( '%s:%s => %s', $this->hostname, $this->port, $message ) );
279
+ }
280
+ private function debug($message) {
281
+ $this->logger->debug ( sprintf ( '%s:%s => %s', $this->hostname, $this->port, $message ) );
282
+ }
283
+ private function error($message) {
284
+ $this->logger->error ( sprintf ( '%s:%s => %s', $this->hostname, $this->port, $message ) );
285
+ }
286
+ }
Postman/Postman-Connectivity-Test/PostmanConnectivityTestController.php CHANGED
@@ -1,382 +1,382 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- class PostmanConnectivityTestController {
7
-
8
- const PORT_TEST_SLUG = 'postman/port_test';
9
-
10
- // logging
11
- private $logger;
12
-
13
- // Holds the values to be used in the fields callbacks
14
- private $rootPluginFilenameAndPath;
15
-
16
- /**
17
- * Constructor
18
- *
19
- * @param mixed $rootPluginFilenameAndPath
20
- */
21
- public function __construct( $rootPluginFilenameAndPath ) {
22
- assert( ! empty( $rootPluginFilenameAndPath ) );
23
- assert( PostmanUtils::isAdmin() );
24
- assert( is_admin() );
25
-
26
- $this->logger = new PostmanLogger( get_class( $this ) );
27
- $this->rootPluginFilenameAndPath = $rootPluginFilenameAndPath;
28
-
29
- PostmanUtils::registerAdminMenu( $this, 'addPortTestSubmenu' );
30
-
31
- // hook on the init event
32
- add_action( 'init', array(
33
- $this,
34
- 'on_init',
35
- ) );
36
-
37
- // initialize the scripts, stylesheets and form fields
38
- add_action( 'admin_init', array(
39
- $this,
40
- 'on_admin_init',
41
- ) );
42
- }
43
-
44
- /**
45
- * Functions to execute on the init event
46
- *
47
- * "Typically used by plugins to initialize. The current user is already authenticated by this time."
48
- * ref: http://codex.wordpress.org/Plugin_API/Action_Reference#Actions_Run_During_a_Typical_Request
49
- */
50
- public function on_init() {
51
- // register Ajax handlers
52
- new PostmanPortTestAjaxController();
53
- }
54
-
55
- /**
56
- * Fires on the admin_init method
57
- */
58
- public function on_admin_init() {
59
- $this->registerStylesAndScripts();
60
- }
61
-
62
- /**
63
- * Register and add settings
64
- */
65
- private function registerStylesAndScripts() {
66
- if ( $this->logger->isTrace() ) {
67
- $this->logger->trace( 'registerStylesAndScripts()' );
68
- }
69
- // register the stylesheet and javascript external resources
70
- $pluginData = apply_filters( 'postman_get_plugin_metadata', null );
71
- wp_register_script( 'postman_port_test_script', plugins_url( 'Postman/Postman-Connectivity-Test/postman_port_test.js', $this->rootPluginFilenameAndPath ), array(
72
- PostmanViewController::JQUERY_SCRIPT,
73
- 'jquery_validation',
74
- PostmanViewController::POSTMAN_SCRIPT,
75
- 'sprintf',
76
- ), $pluginData ['version'] );
77
- }
78
-
79
- /**
80
- * Register the Email Test screen
81
- */
82
- public function addPortTestSubmenu() {
83
- $page = add_submenu_page( null, sprintf( __( '%s Setup', 'post-smtp' ), __( 'Postman SMTP', 'post-smtp' ) ), __( 'Postman SMTP', 'post-smtp' ), Postman::MANAGE_POSTMAN_CAPABILITY_NAME, PostmanConnectivityTestController::PORT_TEST_SLUG, array(
84
- $this,
85
- 'outputPortTestContent',
86
- ) );
87
- // When the plugin options page is loaded, also load the stylesheet
88
- add_action( 'admin_print_styles-' . $page, array(
89
- $this,
90
- 'enqueuePortTestResources',
91
- ) );
92
- }
93
-
94
- /**
95
- */
96
- function enqueuePortTestResources() {
97
- wp_enqueue_style( PostmanViewController::POSTMAN_STYLE );
98
- wp_enqueue_script( 'postman_port_test_script' );
99
- $warning = __( 'Warning', 'post-smtp' );
100
-
101
- wp_localize_script( PostmanViewController::POSTMAN_SCRIPT, 'postman_email_test', array(
102
- 'recipient' => '#' . PostmanSendTestEmailController::RECIPIENT_EMAIL_FIELD_NAME,
103
- 'not_started' => _x( 'In Outbox', 'Email Test Status', 'post-smtp' ),
104
- 'sending' => _x( 'Sending...', 'Email Test Status', 'post-smtp' ),
105
- 'success' => _x( 'Success', 'Email Test Status', 'post-smtp' ),
106
- 'failed' => _x( 'Failed', 'Email Test Status', 'post-smtp' ),
107
- 'ajax_error' => __( 'Ajax Error', 'post-smtp' ),
108
- ) );
109
- PostmanConnectivityTestController::addLocalizeScriptForPortTest();
110
- }
111
- static function addLocalizeScriptForPortTest() {
112
- wp_localize_script( PostmanViewController::POSTMAN_SCRIPT, 'postman_port_test', array(
113
- 'in_progress' => _x( 'Checking..', 'The "please wait" message', 'post-smtp' ),
114
- 'open' => _x( 'Open', 'The port is open', 'post-smtp' ),
115
- 'closed' => _x( 'Closed', 'The port is closed', 'post-smtp' ),
116
- 'yes' => __( 'Yes', 'post-smtp' ),
117
- 'no' => __( 'No', 'post-smtp' ),
118
- /* translators: where %d is a port number */
119
- 'blocked' => __( 'No outbound route between this site and the Internet on Port %d.', 'post-smtp' ),
120
- /* translators: where %d is a port number and %s is a hostname */
121
- 'try_dif_smtp' => __( 'Port %d is open, but not to %s.', 'post-smtp' ),
122
- /* translators: where %d is the port number and %s is the hostname */
123
- 'success' => __( 'Port %d can be used for SMTP to %s.', 'post-smtp' ),
124
- 'mitm' => sprintf( '%s: %s', __( 'Warning', 'post-smtp' ), __( 'connected to %1$s instead of %2$s.', 'post-smtp' ) ),
125
- /* translators: where %d is a port number and %s is the URL for the Postman Gmail Extension */
126
- 'https_success' => __( 'Port %d can be used with the %s.', 'post-smtp' ),
127
- ) );
128
- }
129
-
130
- /**
131
- * Get the settings option array and print one of its values
132
- */
133
- public function port_test_hostname_callback() {
134
- $hostname = PostmanTransportRegistry::getInstance()->getSelectedTransport()->getHostname();
135
- if ( empty( $hostname ) ) {
136
- $hostname = PostmanTransportRegistry::getInstance()->getActiveTransport()->getHostname();
137
- }
138
- printf( '<input type="text" id="input_hostname" name="postman_options[hostname]" value="%s" size="40" class="required"/>', $hostname );
139
- }
140
-
141
- /**
142
- */
143
- public function outputPortTestContent() {
144
- print '<div class="wrap">';
145
-
146
- wp_nonce_field('post-smtp', 'security');
147
-
148
- PostmanViewController::outputChildPageHeader( __( 'Connectivity Test', 'post-smtp' ) );
149
-
150
- print '<p>';
151
- print __( 'This test determines which well-known ports are available for Postman to use.', 'post-smtp' );
152
- print '<form id="port_test_form_id" method="post">';
153
-
154
- wp_nonce_field('post-smtp', 'security' );
155
-
156
- printf( '<label for="hostname">%s</label>', __( 'Outgoing Mail Server Hostname', 'post-smtp' ) );
157
- $this->port_test_hostname_callback();
158
- submit_button( _x( 'Begin Test', 'Button Label', 'post-smtp' ), 'primary', 'begin-port-test', true );
159
- print '</form>';
160
- print '<table id="connectivity_test_table">';
161
- print sprintf( '<tr><th rowspan="2">%s</th><th rowspan="2">%s</th><th rowspan="2">%s</th><th rowspan="2">%s</th><th rowspan="2">%s</th><th colspan="5">%s</th></tr>', __( 'Transport', 'post-smtp' ), _x( 'Socket', 'A socket is the network term for host and port together', 'post-smtp' ), __( 'Status', 'post-smtp' ) . '<sup>*</sup>', __( 'Service Available', 'post-smtp' ), __( 'Server ID', 'post-smtp' ), __( 'Authentication', 'post-smtp' ) );
162
- print sprintf( '<tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th></tr>', 'None', 'Login', 'Plain', 'CRAM-MD5', 'OAuth 2.0' );
163
- $sockets = PostmanTransportRegistry::getInstance()->getSocketsForSetupWizardToProbe();
164
- foreach ( $sockets as $socket ) {
165
- if ( $socket ['smtp'] ) {
166
- print sprintf( '<tr id="%s"><th class="name">%s</th><td class="socket">%s:%s</td><td class="firewall resettable">-</td><td class="service resettable">-</td><td class="reported_id resettable">-</td><td class="auth_none resettable">-</td><td class="auth_login resettable">-</td><td class="auth_plain resettable">-</td><td class="auth_crammd5 resettable">-</td><td class="auth_xoauth2 resettable">-</td></tr>', $socket ['id'], $socket ['transport_name'], $socket ['host'], $socket ['port'] );
167
- } else {
168
- print sprintf( '<tr id="%s"><th class="name">%s</th><td class="socket">%s:%s</td><td class="firewall resettable">-</td><td class="service resettable">-</td><td class="reported_id resettable">-</td><td colspan="5">%s</td></tr>', $socket ['id'], $socket ['transport_name'], $socket ['host'], $socket ['port'], __( 'n/a', 'post-smtp' ) );
169
- }
170
- }
171
- print '</table>';
172
- /* Translators: Where %s is the name of the service providing Internet connectivity test */
173
- printf( '<p class="portquiz" style="display:none; font-size:0.8em">* %s</p>', sprintf( __( 'According to %s', 'post-smtp' ), '<a target="_blank" href="http://portquiz.net">portquiz.net</a>' ) );
174
- printf( '<p class="ajax-loader" style="display:none"><img src="%s"/></p>', plugins_url( 'post-smtp/style/ajax-loader.gif' ) );
175
- print '<section id="conclusion" style="display:none">';
176
- print sprintf( '<h3>%s:</h3>', __( 'Summary', 'post-smtp' ) );
177
- print '<ol class="conclusion">';
178
- print '</ol>';
179
- print '</section>';
180
- print '<section id="blocked-port-help" style="display:none">';
181
- print sprintf( '<p><b>%s</b></p>', __( 'A test with <span style="color:red">"No"</span> Service Available indicates one or more of these issues:', 'post-smtp' ) );
182
- print '<ol>';
183
- printf( '<li>%s</li>', __( 'Your web host has placed a firewall between this site and the Internet', 'post-smtp' ) );
184
- printf( '<li>%s</li>', __( 'The SMTP hostname is wrong or the mail server does not provide service on this port', 'post-smtp' ) );
185
- /* translators: where (1) is the URL and (2) is the system */
186
- $systemBlockMessage = __( 'Your <a href="%1$s">%2$s configuration</a> is preventing outbound connections', 'post-smtp' );
187
- printf( '<li>%s</li>', sprintf( $systemBlockMessage, 'http://php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen', 'PHP' ) );
188
- printf( '<li>%s</li>', sprintf( $systemBlockMessage, 'http://wp-mix.com/disable-external-url-requests/', 'WordPress' ) );
189
- print '</ol></p>';
190
- print sprintf( '<p><b>%s</b></p>', __( 'If the issues above can not be resolved, your last option is to configure Postman to use an email account managed by your web host with an SMTP server managed by your web host.', 'post-smtp' ) );
191
- print '</section>';
192
- print '</div>';
193
- }
194
- }
195
-
196
- /**
197
- *
198
- * @author jasonhendriks
199
- */
200
- class PostmanPortTestAjaxController {
201
- private $logger;
202
- /**
203
- * Constructor
204
- *
205
- * @param PostmanOptions $options
206
- */
207
- function __construct() {
208
- $this->logger = new PostmanLogger( get_class( $this ) );
209
- PostmanUtils::registerAjaxHandler( 'postman_get_hosts_to_test', $this, 'getPortsToTestViaAjax' );
210
- PostmanUtils::registerAjaxHandler( 'postman_wizard_port_test', $this, 'runSmtpTest' );
211
- PostmanUtils::registerAjaxHandler( 'postman_wizard_port_test_smtps', $this, 'runSmtpsTest' );
212
- PostmanUtils::registerAjaxHandler( 'postman_port_quiz_test', $this, 'runPortQuizTest' );
213
- PostmanUtils::registerAjaxHandler( 'postman_test_port', $this, 'runSmtpTest' );
214
- PostmanUtils::registerAjaxHandler( 'postman_test_smtps', $this, 'runSmtpsTest' );
215
- }
216
-
217
- /**
218
- * This Ajax function determines which hosts/ports to test in both the Wizard Connectivity Test and direct Connectivity Test
219
- *
220
- * Given a single outgoing smtp server hostname, return an array of host/port
221
- * combinations to run the connectivity test on
222
- */
223
- function getPortsToTestViaAjax() {
224
-
225
- check_admin_referer('post-smtp', 'security');
226
-
227
- if( !current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_NAME ) ) {
228
- wp_send_json_error(
229
- array(
230
- 'Message' => 'Unauthorized.'
231
- ),
232
- 401
233
- );
234
- }
235
-
236
- $queryHostname = PostmanUtils::getRequestParameter( 'hostname' );
237
- // originalSmtpServer is what SmtpDiscovery thinks the SMTP server should be, given an email address
238
- $originalSmtpServer = PostmanUtils::getRequestParameter( 'original_smtp_server' );
239
- if ( $this->logger->isDebug() ) {
240
- $this->logger->debug( 'Probing available transports for sockets against hostname ' . $queryHostname );
241
- }
242
- $sockets = PostmanTransportRegistry::getInstance()->getSocketsForSetupWizardToProbe( $queryHostname, $originalSmtpServer );
243
- $response = array(
244
- 'hosts' => $sockets,
245
- );
246
- wp_send_json_success( $response );
247
- }
248
-
249
- /**
250
- * This Ajax function retrieves whether a TCP port is open or not
251
- */
252
- function runPortQuizTest() {
253
-
254
- check_admin_referer('post-smtp', 'security');
255
-
256
- if( !current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_NAME ) ) {
257
- wp_send_json_error(
258
- array(
259
- 'Message' => 'Unauthorized.'
260
- ),
261
- 401
262
- );
263
- }
264
-
265
- $hostname = 'portquiz.net';
266
- $port = intval( PostmanUtils::getRequestParameter( 'port' ) );
267
- $this->logger->debug( 'testing TCP port: hostname ' . $hostname . ' port ' . $port );
268
- $portTest = new PostmanPortTest( $hostname, $port );
269
- $success = $portTest->genericConnectionTest();
270
- $this->buildResponse( $hostname, $port, $portTest, $success );
271
- }
272
-
273
- /**
274
- * This Ajax function retrieves whether a TCP port is open or not.
275
- * This is called by both the Wizard and Port Test
276
- */
277
- function runSmtpTest() {
278
-
279
- check_admin_referer('post-smtp', 'security');
280
-
281
- if( !current_user_can( 'delete_users' ) ) {
282
- wp_send_json_error(
283
- array(
284
- 'Message' => 'Unauthorized.'
285
- ),
286
- 401
287
- );
288
- }
289
-
290
- $hostname = trim( PostmanUtils::getRequestParameter( 'hostname' ) );
291
- $port = intval( PostmanUtils::getRequestParameter( 'port' ) );
292
- $transport = trim( PostmanUtils::getRequestParameter( 'transport' ) );
293
- $timeout = PostmanUtils::getRequestParameter( 'timeout' );
294
- $logo_url = PostmanUtils::getRequestParameter( 'logo_url' );
295
- $data['logo_url'] = $logo_url;
296
-
297
- $this->logger->trace( $timeout );
298
- $portTest = new PostmanPortTest( $hostname, $port );
299
- if ( isset( $timeout ) ) {
300
- $portTest->setConnectionTimeout( intval( $timeout ) );
301
- $portTest->setReadTimeout( intval( $timeout ) );
302
- }
303
- if ( $port != 443 ) {
304
- $this->logger->debug( sprintf( 'testing SMTP socket %s:%s (%s)', $hostname, $port, $transport ) );
305
- $success = $portTest->testSmtpPorts();
306
- } else {
307
- $this->logger->debug( sprintf( 'testing HTTPS socket %s:%s (%s)', $hostname, $port, $transport ) );
308
- $success = $portTest->testHttpPorts();
309
- }
310
-
311
- $this->buildResponse( $hostname, $port, $portTest, $success, $transport, $data );
312
- }
313
- /**
314
- * This Ajax function retrieves whether a TCP port is open or not
315
- */
316
- function runSmtpsTest() {
317
-
318
- check_admin_referer('post-smtp', 'security');
319
-
320
- if( !current_user_can( 'delete_users' ) ) {
321
- wp_send_json_error(
322
- array(
323
- 'Message' => 'Unauthorized.'
324
- ),
325
- 401
326
- );
327
- }
328
-
329
- $hostname = trim( PostmanUtils::getRequestParameter( 'hostname' ) );
330
- $port = intval( PostmanUtils::getRequestParameter( 'port' ) );
331
- $transport = trim( PostmanUtils::getRequestParameter( 'transport' ) );
332
- $transportName = trim( PostmanUtils::getRequestParameter( 'transport_name' ) );
333
- $logo_url = PostmanUtils::getRequestParameter( 'logo_url' );
334
- $data['logo_url'] = $logo_url;
335
-
336
- $this->logger->debug( sprintf( 'testing SMTPS socket %s:%s (%s)', $hostname, $port, $transport ) );
337
- $portTest = new PostmanPortTest( $hostname, $port );
338
- $portTest->transportName = $transportName;
339
- $success = $portTest->testSmtpsPorts();
340
- $this->buildResponse( $hostname, $port, $portTest, $success, $transport, $data );
341
- }
342
-
343
- /**
344
- *
345
- * @param mixed $hostname
346
- * @param mixed $port
347
- * @param mixed $success
348
- * @since 2.1 @param mixed $data for extra fields
349
- */
350
- private function buildResponse( $hostname, $port, PostmanPortTest $portTest, $success, $transport = '', $data = array() ) {
351
- $this->logger->debug( sprintf( 'testing port result for %s:%s success=%s', $hostname, $port, $success ) );
352
- $response = array(
353
- 'hostname' => $hostname,
354
- 'hostname_domain_only' => $portTest->hostnameDomainOnly,
355
- 'port' => $port,
356
- 'protocol' => $portTest->protocol,
357
- 'secure' => ($portTest->secure),
358
- 'mitm' => ($portTest->mitm),
359
- 'reported_hostname' => $portTest->reportedHostname,
360
- 'reported_hostname_domain_only' => $portTest->reportedHostnameDomainOnly,
361
- 'message' => $portTest->getErrorMessage(),
362
- 'start_tls' => $portTest->startTls,
363
- 'auth_plain' => $portTest->authPlain,
364
- 'auth_login' => $portTest->authLogin,
365
- 'auth_crammd5' => $portTest->authCrammd5,
366
- 'auth_xoauth' => $portTest->authXoauth,
367
- 'auth_none' => $portTest->authNone,
368
- 'try_smtps' => $portTest->trySmtps,
369
- 'success' => $success,
370
- 'transport' => $transport,
371
- 'data' => $data
372
- );
373
-
374
- $this->logger->trace( 'Ajax response:' );
375
- $this->logger->trace( $response );
376
- if ( $success ) {
377
- wp_send_json_success( $response );
378
- } else {
379
- wp_send_json_error( $response );
380
- }
381
- }
382
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ class PostmanConnectivityTestController {
7
+
8
+ const PORT_TEST_SLUG = 'postman/port_test';
9
+
10
+ // logging
11
+ private $logger;
12
+
13
+ // Holds the values to be used in the fields callbacks
14
+ private $rootPluginFilenameAndPath;
15
+
16
+ /**
17
+ * Constructor
18
+ *
19
+ * @param mixed $rootPluginFilenameAndPath
20
+ */
21
+ public function __construct( $rootPluginFilenameAndPath ) {
22
+ assert( ! empty( $rootPluginFilenameAndPath ) );
23
+ assert( PostmanUtils::isAdmin() );
24
+ assert( is_admin() );
25
+
26
+ $this->logger = new PostmanLogger( get_class( $this ) );
27
+ $this->rootPluginFilenameAndPath = $rootPluginFilenameAndPath;
28
+
29
+ PostmanUtils::registerAdminMenu( $this, 'addPortTestSubmenu' );
30
+
31
+ // hook on the init event
32
+ add_action( 'init', array(
33
+ $this,
34
+ 'on_init',
35
+ ) );
36
+
37
+ // initialize the scripts, stylesheets and form fields
38
+ add_action( 'admin_init', array(
39
+ $this,
40
+ 'on_admin_init',
41
+ ) );
42
+ }
43
+
44
+ /**
45
+ * Functions to execute on the init event
46
+ *
47
+ * "Typically used by plugins to initialize. The current user is already authenticated by this time."
48
+ * ref: http://codex.wordpress.org/Plugin_API/Action_Reference#Actions_Run_During_a_Typical_Request
49
+ */
50
+ public function on_init() {
51
+ // register Ajax handlers
52
+ new PostmanPortTestAjaxController();
53
+ }
54
+
55
+ /**
56
+ * Fires on the admin_init method
57
+ */
58
+ public function on_admin_init() {
59
+ $this->registerStylesAndScripts();
60
+ }
61
+
62
+ /**
63
+ * Register and add settings
64
+ */
65
+ private function registerStylesAndScripts() {
66
+ if ( $this->logger->isTrace() ) {
67
+ $this->logger->trace( 'registerStylesAndScripts()' );
68
+ }
69
+ // register the stylesheet and javascript external resources
70
+ $pluginData = apply_filters( 'postman_get_plugin_metadata', null );
71
+ wp_register_script( 'postman_port_test_script', plugins_url( 'Postman/Postman-Connectivity-Test/postman_port_test.js', $this->rootPluginFilenameAndPath ), array(
72
+ PostmanViewController::JQUERY_SCRIPT,
73
+ 'jquery_validation',
74
+ PostmanViewController::POSTMAN_SCRIPT,
75
+ 'sprintf',
76
+ ), $pluginData ['version'] );
77
+ }
78
+
79
+ /**
80
+ * Register the Email Test screen
81
+ */
82
+ public function addPortTestSubmenu() {
83
+ $page = add_submenu_page( null, sprintf( __( '%s Setup', 'post-smtp' ), __( 'Postman SMTP', 'post-smtp' ) ), __( 'Postman SMTP', 'post-smtp' ), Postman::MANAGE_POSTMAN_CAPABILITY_NAME, PostmanConnectivityTestController::PORT_TEST_SLUG, array(
84
+ $this,
85
+ 'outputPortTestContent',
86
+ ) );
87
+ // When the plugin options page is loaded, also load the stylesheet
88
+ add_action( 'admin_print_styles-' . $page, array(
89
+ $this,
90
+ 'enqueuePortTestResources',
91
+ ) );
92
+ }
93
+
94
+ /**
95
+ */
96
+ function enqueuePortTestResources() {
97
+ wp_enqueue_style( PostmanViewController::POSTMAN_STYLE );
98
+ wp_enqueue_script( 'postman_port_test_script' );
99
+ $warning = __( 'Warning', 'post-smtp' );
100
+
101
+ wp_localize_script( PostmanViewController::POSTMAN_SCRIPT, 'postman_email_test', array(
102
+ 'recipient' => '#' . PostmanSendTestEmailController::RECIPIENT_EMAIL_FIELD_NAME,
103
+ 'not_started' => _x( 'In Outbox', 'Email Test Status', 'post-smtp' ),
104
+ 'sending' => _x( 'Sending...', 'Email Test Status', 'post-smtp' ),
105
+ 'success' => _x( 'Success', 'Email Test Status', 'post-smtp' ),
106
+ 'failed' => _x( 'Failed', 'Email Test Status', 'post-smtp' ),
107
+ 'ajax_error' => __( 'Ajax Error', 'post-smtp' ),
108
+ ) );
109
+ PostmanConnectivityTestController::addLocalizeScriptForPortTest();
110
+ }
111
+ static function addLocalizeScriptForPortTest() {
112
+ wp_localize_script( PostmanViewController::POSTMAN_SCRIPT, 'postman_port_test', array(
113
+ 'in_progress' => _x( 'Checking..', 'The "please wait" message', 'post-smtp' ),
114
+ 'open' => _x( 'Open', 'The port is open', 'post-smtp' ),
115
+ 'closed' => _x( 'Closed', 'The port is closed', 'post-smtp' ),
116
+ 'yes' => __( 'Yes', 'post-smtp' ),
117
+ 'no' => __( 'No', 'post-smtp' ),
118
+ /* translators: where %d is a port number */
119
+ 'blocked' => __( 'No outbound route between this site and the Internet on Port %d.', 'post-smtp' ),
120
+ /* translators: where %d is a port number and %s is a hostname */
121
+ 'try_dif_smtp' => __( 'Port %d is open, but not to %s.', 'post-smtp' ),
122
+ /* translators: where %d is the port number and %s is the hostname */
123
+ 'success' => __( 'Port %d can be used for SMTP to %s.', 'post-smtp' ),
124
+ 'mitm' => sprintf( '%s: %s', __( 'Warning', 'post-smtp' ), __( 'connected to %1$s instead of %2$s.', 'post-smtp' ) ),
125
+ /* translators: where %d is a port number and %s is the URL for the Postman Gmail Extension */
126
+ 'https_success' => __( 'Port %d can be used with the %s.', 'post-smtp' ),
127
+ ) );
128
+ }
129
+
130
+ /**
131
+ * Get the settings option array and print one of its values
132
+ */
133
+ public function port_test_hostname_callback() {
134
+ $hostname = PostmanTransportRegistry::getInstance()->getSelectedTransport()->getHostname();
135
+ if ( empty( $hostname ) ) {
136
+ $hostname = PostmanTransportRegistry::getInstance()->getActiveTransport()->getHostname();
137
+ }
138
+ printf( '<input type="text" id="input_hostname" name="postman_options[hostname]" value="%s" size="40" class="required"/>', $hostname );
139
+ }
140
+
141
+ /**
142
+ */
143
+ public function outputPortTestContent() {
144
+ print '<div class="wrap">';
145
+
146
+ wp_nonce_field('post-smtp', 'security');
147
+
148
+ PostmanViewController::outputChildPageHeader( __( 'Connectivity Test', 'post-smtp' ) );
149
+
150
+ print '<p>';
151
+ print __( 'This test determines which well-known ports are available for Postman to use.', 'post-smtp' );
152
+ print '<form id="port_test_form_id" method="post">';
153
+
154
+ wp_nonce_field('post-smtp', 'security' );
155
+
156
+ printf( '<label for="hostname">%s</label>', __( 'Outgoing Mail Server Hostname', 'post-smtp' ) );
157
+ $this->port_test_hostname_callback();
158
+ submit_button( _x( 'Begin Test', 'Button Label', 'post-smtp' ), 'primary', 'begin-port-test', true );
159
+ print '</form>';
160
+ print '<table id="connectivity_test_table">';
161
+ print sprintf( '<tr><th rowspan="2">%s</th><th rowspan="2">%s</th><th rowspan="2">%s</th><th rowspan="2">%s</th><th rowspan="2">%s</th><th colspan="5">%s</th></tr>', __( 'Transport', 'post-smtp' ), _x( 'Socket', 'A socket is the network term for host and port together', 'post-smtp' ), __( 'Status', 'post-smtp' ) . '<sup>*</sup>', __( 'Service Available', 'post-smtp' ), __( 'Server ID', 'post-smtp' ), __( 'Authentication', 'post-smtp' ) );
162
+ print sprintf( '<tr><th>%s</th><th>%s</th><th>%s</th><th>%s</th><th>%s</th></tr>', 'None', 'Login', 'Plain', 'CRAM-MD5', 'OAuth 2.0' );
163
+ $sockets = PostmanTransportRegistry::getInstance()->getSocketsForSetupWizardToProbe();
164
+ foreach ( $sockets as $socket ) {
165
+ if ( $socket ['smtp'] ) {
166
+ print sprintf( '<tr id="%s"><th class="name">%s</th><td class="socket">%s:%s</td><td class="firewall resettable">-</td><td class="service resettable">-</td><td class="reported_id resettable">-</td><td class="auth_none resettable">-</td><td class="auth_login resettable">-</td><td class="auth_plain resettable">-</td><td class="auth_crammd5 resettable">-</td><td class="auth_xoauth2 resettable">-</td></tr>', $socket ['id'], $socket ['transport_name'], $socket ['host'], $socket ['port'] );
167
+ } else {
168
+ print sprintf( '<tr id="%s"><th class="name">%s</th><td class="socket">%s:%s</td><td class="firewall resettable">-</td><td class="service resettable">-</td><td class="reported_id resettable">-</td><td colspan="5">%s</td></tr>', $socket ['id'], $socket ['transport_name'], $socket ['host'], $socket ['port'], __( 'n/a', 'post-smtp' ) );
169
+ }
170
+ }
171
+ print '</table>';
172
+ /* Translators: Where %s is the name of the service providing Internet connectivity test */
173
+ printf( '<p class="portquiz" style="display:none; font-size:0.8em">* %s</p>', sprintf( __( 'According to %s', 'post-smtp' ), '<a target="_blank" href="http://portquiz.net">portquiz.net</a>' ) );
174
+ printf( '<p class="ajax-loader" style="display:none"><img src="%s"/></p>', plugins_url( 'post-smtp/style/ajax-loader.gif' ) );
175
+ print '<section id="conclusion" style="display:none">';
176
+ print sprintf( '<h3>%s:</h3>', __( 'Summary', 'post-smtp' ) );
177
+ print '<ol class="conclusion">';
178
+ print '</ol>';
179
+ print '</section>';
180
+ print '<section id="blocked-port-help" style="display:none">';
181
+ print sprintf( '<p><b>%s</b></p>', __( 'A test with <span style="color:red">"No"</span> Service Available indicates one or more of these issues:', 'post-smtp' ) );
182
+ print '<ol>';
183
+ printf( '<li>%s</li>', __( 'Your web host has placed a firewall between this site and the Internet', 'post-smtp' ) );
184
+ printf( '<li>%s</li>', __( 'The SMTP hostname is wrong or the mail server does not provide service on this port', 'post-smtp' ) );
185
+ /* translators: where (1) is the URL and (2) is the system */
186
+ $systemBlockMessage = __( 'Your <a href="%1$s">%2$s configuration</a> is preventing outbound connections', 'post-smtp' );
187
+ printf( '<li>%s</li>', sprintf( $systemBlockMessage, 'http://php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen', 'PHP' ) );
188
+ printf( '<li>%s</li>', sprintf( $systemBlockMessage, 'http://wp-mix.com/disable-external-url-requests/', 'WordPress' ) );
189
+ print '</ol></p>';
190
+ print sprintf( '<p><b>%s</b></p>', __( 'If the issues above can not be resolved, your last option is to configure Postman to use an email account managed by your web host with an SMTP server managed by your web host.', 'post-smtp' ) );
191
+ print '</section>';
192
+ print '</div>';
193
+ }
194
+ }
195
+
196
+ /**
197
+ *
198
+ * @author jasonhendriks
199
+ */
200
+ class PostmanPortTestAjaxController {
201
+ private $logger;
202
+ /**
203
+ * Constructor
204
+ *
205
+ * @param PostmanOptions $options
206
+ */
207
+ function __construct() {
208
+ $this->logger = new PostmanLogger( get_class( $this ) );
209
+ PostmanUtils::registerAjaxHandler( 'postman_get_hosts_to_test', $this, 'getPortsToTestViaAjax' );
210
+ PostmanUtils::registerAjaxHandler( 'postman_wizard_port_test', $this, 'runSmtpTest' );
211
+ PostmanUtils::registerAjaxHandler( 'postman_wizard_port_test_smtps', $this, 'runSmtpsTest' );
212
+ PostmanUtils::registerAjaxHandler( 'postman_port_quiz_test', $this, 'runPortQuizTest' );
213
+ PostmanUtils::registerAjaxHandler( 'postman_test_port', $this, 'runSmtpTest' );
214
+ PostmanUtils::registerAjaxHandler( 'postman_test_smtps', $this, 'runSmtpsTest' );
215
+ }
216
+
217
+ /**
218
+ * This Ajax function determines which hosts/ports to test in both the Wizard Connectivity Test and direct Connectivity Test
219
+ *
220
+ * Given a single outgoing smtp server hostname, return an array of host/port
221
+ * combinations to run the connectivity test on
222
+ */
223
+ function getPortsToTestViaAjax() {
224
+
225
+ check_admin_referer('post-smtp', 'security');
226
+
227
+ if( !current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_NAME ) ) {
228
+ wp_send_json_error(
229
+ array(
230
+ 'Message' => 'Unauthorized.'
231
+ ),
232
+ 401
233
+ );
234
+ }
235
+
236
+ $queryHostname = PostmanUtils::getRequestParameter( 'hostname' );
237
+ // originalSmtpServer is what SmtpDiscovery thinks the SMTP server should be, given an email address
238
+ $originalSmtpServer = PostmanUtils::getRequestParameter( 'original_smtp_server' );
239
+ if ( $this->logger->isDebug() ) {
240
+ $this->logger->debug( 'Probing available transports for sockets against hostname ' . $queryHostname );
241
+ }
242
+ $sockets = PostmanTransportRegistry::getInstance()->getSocketsForSetupWizardToProbe( $queryHostname, $originalSmtpServer );
243
+ $response = array(
244
+ 'hosts' => $sockets,
245
+ );
246
+ wp_send_json_success( $response );
247
+ }
248
+
249
+ /**
250
+ * This Ajax function retrieves whether a TCP port is open or not
251
+ */
252
+ function runPortQuizTest() {
253
+
254
+ check_admin_referer('post-smtp', 'security');
255
+
256
+ if( !current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_NAME ) ) {
257
+ wp_send_json_error(
258
+ array(
259
+ 'Message' => 'Unauthorized.'
260
+ ),
261
+ 401
262
+ );
263
+ }
264
+
265
+ $hostname = 'portquiz.net';
266
+ $port = intval( PostmanUtils::getRequestParameter( 'port' ) );
267
+ $this->logger->debug( 'testing TCP port: hostname ' . $hostname . ' port ' . $port );
268
+ $portTest = new PostmanPortTest( $hostname, $port );
269
+ $success = $portTest->genericConnectionTest();
270
+ $this->buildResponse( $hostname, $port, $portTest, $success );
271
+ }
272
+
273
+ /**
274
+ * This Ajax function retrieves whether a TCP port is open or not.
275
+ * This is called by both the Wizard and Port Test
276
+ */
277
+ function runSmtpTest() {
278
+
279
+ check_admin_referer('post-smtp', 'security');
280
+
281
+ if( !current_user_can( 'delete_users' ) ) {
282
+ wp_send_json_error(
283
+ array(
284
+ 'Message' => 'Unauthorized.'
285
+ ),
286
+ 401
287
+ );
288
+ }
289
+
290
+ $hostname = trim( PostmanUtils::getRequestParameter( 'hostname' ) );
291
+ $port = intval( PostmanUtils::getRequestParameter( 'port' ) );
292
+ $transport = trim( PostmanUtils::getRequestParameter( 'transport' ) );
293
+ $timeout = PostmanUtils::getRequestParameter( 'timeout' );
294
+ $logo_url = PostmanUtils::getRequestParameter( 'logo_url' );
295
+ $data['logo_url'] = $logo_url;
296
+
297
+ $this->logger->trace( $timeout );
298
+ $portTest = new PostmanPortTest( $hostname, $port );
299
+ if ( isset( $timeout ) ) {
300
+ $portTest->setConnectionTimeout( intval( $timeout ) );
301
+ $portTest->setReadTimeout( intval( $timeout ) );
302
+ }
303
+ if ( $port != 443 ) {
304
+ $this->logger->debug( sprintf( 'testing SMTP socket %s:%s (%s)', $hostname, $port, $transport ) );
305
+ $success = $portTest->testSmtpPorts();
306
+ } else {
307
+ $this->logger->debug( sprintf( 'testing HTTPS socket %s:%s (%s)', $hostname, $port, $transport ) );
308
+ $success = $portTest->testHttpPorts();
309
+ }
310
+
311
+ $this->buildResponse( $hostname, $port, $portTest, $success, $transport, $data );
312
+ }
313
+ /**
314
+ * This Ajax function retrieves whether a TCP port is open or not
315
+ */
316
+ function runSmtpsTest() {
317
+
318
+ check_admin_referer('post-smtp', 'security');
319
+
320
+ if( !current_user_can( 'delete_users' ) ) {
321
+ wp_send_json_error(
322
+ array(
323
+ 'Message' => 'Unauthorized.'
324
+ ),
325
+ 401
326
+ );
327
+ }
328
+
329
+ $hostname = trim( PostmanUtils::getRequestParameter( 'hostname' ) );
330
+ $port = intval( PostmanUtils::getRequestParameter( 'port' ) );
331
+ $transport = trim( PostmanUtils::getRequestParameter( 'transport' ) );
332
+ $transportName = trim( PostmanUtils::getRequestParameter( 'transport_name' ) );
333
+ $logo_url = PostmanUtils::getRequestParameter( 'logo_url' );
334
+ $data['logo_url'] = $logo_url;
335
+
336
+ $this->logger->debug( sprintf( 'testing SMTPS socket %s:%s (%s)', $hostname, $port, $transport ) );
337
+ $portTest = new PostmanPortTest( $hostname, $port );
338
+ $portTest->transportName = $transportName;
339
+ $success = $portTest->testSmtpsPorts();
340
+ $this->buildResponse( $hostname, $port, $portTest, $success, $transport, $data );
341
+ }
342
+
343
+ /**
344
+ *
345
+ * @param mixed $hostname
346
+ * @param mixed $port
347
+ * @param mixed $success
348
+ * @since 2.1 @param mixed $data for extra fields
349
+ */
350
+ private function buildResponse( $hostname, $port, PostmanPortTest $portTest, $success, $transport = '', $data = array() ) {
351
+ $this->logger->debug( sprintf( 'testing port result for %s:%s success=%s', $hostname, $port, $success ) );
352
+ $response = array(
353
+ 'hostname' => $hostname,
354
+ 'hostname_domain_only' => $portTest->hostnameDomainOnly,
355
+ 'port' => $port,
356
+ 'protocol' => $portTest->protocol,
357
+ 'secure' => ($portTest->secure),
358
+ 'mitm' => ($portTest->mitm),
359
+ 'reported_hostname' => $portTest->reportedHostname,
360
+ 'reported_hostname_domain_only' => $portTest->reportedHostnameDomainOnly,
361
+ 'message' => $portTest->getErrorMessage(),
362
+ 'start_tls' => $portTest->startTls,
363
+ 'auth_plain' => $portTest->authPlain,
364
+ 'auth_login' => $portTest->authLogin,
365
+ 'auth_crammd5' => $portTest->authCrammd5,
366
+ 'auth_xoauth' => $portTest->authXoauth,
367
+ 'auth_none' => $portTest->authNone,
368
+ 'try_smtps' => $portTest->trySmtps,
369
+ 'success' => $success,
370
+ 'transport' => $transport,
371
+ 'data' => $data
372
+ );
373
+
374
+ $this->logger->trace( 'Ajax response:' );
375
+ $this->logger->trace( $response );
376
+ if ( $success ) {
377
+ wp_send_json_success( $response );
378
+ } else {
379
+ wp_send_json_error( $response );
380
+ }
381
+ }
382
+ }
Postman/Postman-Connectivity-Test/postman_port_test.js CHANGED
@@ -1,336 +1,336 @@
1
- postman_begin_test_button_id = 'input#begin-port-test';
2
-
3
- jQuery(document).ready(function() {
4
- var elHostname = jQuery(postman_begin_test_button_id);
5
- jQuery(post_smtp_localize.postman_hostname_element_name).focus();
6
- elHostname.click(function() {
7
- valid = jQuery('#port_test_form_id').valid();
8
- if (!valid) {
9
- return false;
10
- }
11
-
12
- // initialize the view for a new test
13
- elHostname.attr('disabled', 'disabled');
14
- hide('#conclusion');
15
- hide('#blocked-port-help');
16
- jQuery('ol.conclusion').html('');
17
- showLoaderIcon();
18
-
19
- var $elTestingTable = jQuery('#connectivity_test_table');
20
- $elTestingTable.show();
21
- show('.portquiz');
22
-
23
- var hostname = jQuery(post_smtp_localize.postman_hostname_element_name).val();
24
- var data = {
25
- 'action' : 'postman_get_hosts_to_test',
26
- 'hostname' : hostname,
27
- 'security' : jQuery('#security').val(),
28
- };
29
-
30
- totalPortsTested = 0;
31
- portsToBeTested = 0;
32
-
33
- jQuery.post(ajaxurl, data, function(response) {
34
- if (postmanValidateAjaxResponseWithPopup(response)) {
35
- handleHostsToCheckResponse(response.data);
36
- }
37
- }).fail(function(response) {
38
- ajaxFailed(response);
39
- });
40
-
41
- //
42
- return false;
43
- });
44
- });
45
-
46
- /**
47
- * Handles the response from the server of the list of sockets to check.
48
- *
49
- * @param hostname
50
- * @param response
51
- */
52
- function handleHostsToCheckResponse(response) {
53
- for ( var x in response.hosts) {
54
- var id = response.hosts[x].id;
55
- var transportSlug = response.hosts[x].transport_id;
56
- var hostname = response.hosts[x].host;
57
- var port = response.hosts[x].port
58
- var cell = 'tr#' + id + " td.socket";
59
- var testEl = jQuery(cell);
60
- testEl.html('<span>' + hostname + ':' + port + '</span>');
61
- portQuizTest(response.hosts[x], hostname, port);
62
- }
63
- }
64
-
65
- function portQuizTest(socket, hostname, port) {
66
- resetView(socket.id);
67
- portsToBeTested += 1;
68
- var cell = 'tr#' + socket.id + " td.firewall";
69
- var testEl = jQuery(cell);
70
- testEl.html('<span style="color:blue">' + postman_port_test.in_progress
71
- + '</span>');
72
- var data = {
73
- 'action' : 'postman_port_quiz_test',
74
- 'hostname' : hostname,
75
- 'port' : port,
76
- 'security' : jQuery('#security').val(),
77
- };
78
- jQuery.post(
79
- ajaxurl,
80
- data,
81
- function(response) {
82
- if (postmanValidateAjaxResponseWithPopup(response)) {
83
- if (response.success) {
84
- testEl.html('<span style="color:green">'
85
- + postman_port_test.open + '</span>');
86
- // start the next test
87
- } else {
88
- testEl.html('<span style="color:red">'
89
- + postman_port_test.closed + '</span>');
90
- }
91
- firstServiceTest(socket, hostname, port, response.success);
92
- }
93
- }).fail(
94
- function(response) {
95
- totalPortsTested += 1;
96
- testEl.html('<span style="color:red">'
97
- + postman_email_test.ajax_error + "</span>");
98
- enableButtonCheck();
99
- });
100
- }
101
- function firstServiceTest(socket, hostname, port, open) {
102
- var cell = 'tr#' + socket.id + " td.service";
103
- var testEl = jQuery(cell);
104
- testEl.html('<span style="color:blue">' + postman_port_test.in_progress
105
- + '</span>');
106
- var data = {
107
- 'action' : 'postman_test_port',
108
- 'hostname' : hostname,
109
- 'port' : port,
110
- 'security' : jQuery('#security').val(),
111
- };
112
- jQuery
113
- .post(
114
- ajaxurl,
115
- data,
116
- function(response) {
117
- if (postmanValidateAjaxResponseWithPopup(response)) {
118
- if (response.success) {
119
- totalPortsTested += 1;
120
- if (port == 443) {
121
- // API test
122
- testEl
123
- .html('<span style="color:green">&#x1f512; '
124
- + response.data.protocol
125
- + '</span>');
126
- var cell = 'tr#' + socket.id
127
- + " td.reported_id";
128
- var p443El = jQuery(cell);
129
- if (response.data.reported_hostname_domain_only) {
130
- p443El
131
- .html('<span>'
132
- + response.data.reported_hostname_domain_only
133
- + '</span>');
134
- }
135
- addConclusion(sprintf(
136
- postman_port_test.https_success,
137
- response.data.port,
138
- socket.transport_name), true,
139
- response.data.secure);
140
- } else {
141
- // SMTP test
142
- testEl.html('<span style="color:green">'
143
- + response.data.protocol
144
- + '</span>');
145
- inspectResponse(socket.id, response.data,
146
- port);
147
- var message = sprintf(postman_port_test.success,
148
- port, hostname);
149
- if (response.data.mitm) {
150
- message += ' <span style="background-color:yellow">'
151
- + sprintf(
152
- postman_port_test.mitm,
153
- response.data.reported_hostname_domain_only,
154
- response.data.hostname_domain_only)
155
- + '</span>';
156
- }
157
- addConclusion(message, true,
158
- response.data.secure);
159
- }
160
- } else {
161
- if (port == 443) {
162
- // API test
163
- testEl.html('<span style="color:red">'
164
- + postman_port_test.no + '</span>');
165
- totalPortsTested += 1;
166
- var p443El = jQuery(cell);
167
- addConclusion(sprintf(postman_port_test.try_dif_smtp,
168
- port, hostname), false,
169
- response.data.secure);
170
- } else {
171
- if (response.data.try_smtps) {
172
- // start the SMTPS test
173
- portTest3(socket, hostname, port, open);
174
- } else {
175
- testEl.html('<span style="color:red">'
176
- + postman_port_test.no + '</span>');
177
- totalPortsTested += 1;
178
- addConclusion(sprintf(
179
- postman_port_test.blocked, port),
180
- false, response.data.secure);
181
- show('#blocked-port-help');
182
- }
183
- }
184
- }
185
- enableButtonCheck();
186
- }
187
- }).fail(
188
- function(response) {
189
- totalPortsTested += 1;
190
- testEl.html('<span style="color:red">'
191
- + postman_email_test.ajax_error + "</span>");
192
- enableButtonCheck();
193
- });
194
- }
195
- function portTest3(socket, hostname, port, open) {
196
- var cell = 'tr#' + socket.id + " td.service";
197
- var testEl = jQuery(cell);
198
- testEl.html('<span style="color:blue">' + postman_port_test.in_progress
199
- + '</span>');
200
- var data = {
201
- 'action' : 'postman_test_smtps',
202
- 'hostname' : hostname,
203
- 'port' : port,
204
- 'security' : jQuery('#security').val(),
205
- };
206
- jQuery
207
- .post(
208
- ajaxurl,
209
- data,
210
- function(response) {
211
- if (postmanValidateAjaxResponseWithPopup(response)) {
212
- if (response.success) {
213
- if (response.data.protocol == 'SMTPS') {
214
- testEl
215
- .html('<span style="color:green">&#x1f512; '
216
- + response.data.protocol
217
- + '</span>');
218
- } else {
219
-
220
- testEl.html('<span style="color:green">'
221
- + response.data.protocol
222
- + '</span>');
223
- }
224
- inspectResponse(socket.id, response.data, port);
225
- var message = sprintf(postman_port_test.success,
226
- port, hostname);
227
- if (response.data.mitm) {
228
- message += ' <span style="background-color:yellow">'
229
- + sprintf(
230
- postman_port_test.mitm,
231
- response.data.reported_hostname_domain_only,
232
- response.data.hostname_domain_only
233
- + '</span>');
234
- }
235
- addConclusion(message, true,
236
- response.data.secure);
237
- } else {
238
- testEl.html('<span style="color:red">'
239
- + postman_port_test.no + '</span>');
240
- show('#blocked-port-help');
241
- if (open) {
242
- addConclusion(sprintf(postman_port_test.try_dif_smtp,
243
- port, hostname), false,
244
- response.data.secure);
245
- } else {
246
- addConclusion(sprintf(postman_port_test.blocked,
247
- port), false, response.data.secure);
248
- }
249
- }
250
- totalPortsTested += 1;
251
- enableButtonCheck();
252
- }
253
- }).fail(
254
- function(response) {
255
- totalPortsTested += 1;
256
- testEl.html('<span style="color:red">'
257
- + postman_email_test.ajax_error + "</span>");
258
- enableButtonCheck();
259
- });
260
- }
261
- function enableButtonCheck() {
262
- if (totalPortsTested >= portsToBeTested) {
263
- enable(postman_begin_test_button_id);
264
- hideLoaderIcon();
265
- jQuery(post_smtp_localize.postman_hostname_element_name).focus();
266
- }
267
- }
268
- function inspectResponse(id, response, port) {
269
- var cell = 'tr#' + id + " td.reported_id";
270
- var testEl = jQuery(cell);
271
- if (response.reported_hostname_domain_only) {
272
- testEl.html('<span>' + response.reported_hostname_domain_only
273
- + '</span>');
274
- }
275
- var cell = 'tr#' + id + " td.service";
276
- var testEl = jQuery(cell);
277
- if (response.protocol == 'SMTPS') {
278
- testEl.html('<span style="color:green">&#x1f512; SMTPS</span>');
279
- } else if (response.start_tls) {
280
- testEl.html('<span style="color:green">&#x1f512; SMTP-STARTTLS</span>');
281
- } else {
282
- testEl.html('<span style="color:green">SMTP</span>');
283
- }
284
- var cell = 'tr#' + id + " td.auth_none";
285
- var testEl = jQuery(cell);
286
- if (response.auth_none) {
287
- testEl.html('<span style="color:green">' + postman_port_test.yes + '</span>');
288
- } else {
289
- testEl.html('<span>' + postman_port_test.no + '</span>');
290
- }
291
- var cell = 'tr#' + id + " td.auth_plain";
292
- var testEl = jQuery(cell);
293
- if (response.auth_plain) {
294
- testEl.html('<span style="color:green">' + postman_port_test.yes + '</span>');
295
- } else {
296
- testEl.html('<span>' + postman_port_test.no + '</span>');
297
- }
298
- var cell = 'tr#' + id + " td.auth_login";
299
- var testEl = jQuery(cell);
300
- if (response.auth_login) {
301
- testEl.html('<span style="color:green">' + postman_port_test.yes + '</span>');
302
- } else {
303
- testEl.html('<span>' + postman_port_test.no + '</span>');
304
- }
305
- var cell = 'tr#' + id + " td.auth_crammd5";
306
- var testEl = jQuery(cell);
307
- if (response.auth_crammd5) {
308
- testEl.html('<span style="color:green">' + postman_port_test.yes + '</span>');
309
- } else {
310
- testEl.html('<span>' + postman_port_test.no + '</span>');
311
- }
312
- var cell = 'tr#' + id + " td.auth_xoauth2";
313
- var testEl = jQuery(cell);
314
- if (response.auth_xoauth) {
315
- testEl.html('<span style="color:green">' + postman_port_test.yes + '</span>');
316
- } else {
317
- testEl.html('<span>' + postman_port_test.no + '</span>');
318
- }
319
- }
320
- function resetView(id) {
321
- var testEl = jQuery('tr#' + id + ' td.resettable');
322
- testEl.html('-');
323
- }
324
- function addConclusion(message, success, isSecure) {
325
- show('#conclusion');
326
- var secureIcon = '';
327
- if (isSecure) {
328
- secureIcon = '&#x1f512; ';
329
- }
330
- if (success) {
331
- message = '&#9989; ' + secureIcon + message;
332
- } else {
333
- message = '&#10060; ' + secureIcon + message;
334
- }
335
- jQuery('ol.conclusion').append('<li>' + message + '</li>');
336
- }
1
+ postman_begin_test_button_id = 'input#begin-port-test';
2
+
3
+ jQuery(document).ready(function() {
4
+ var elHostname = jQuery(postman_begin_test_button_id);
5
+ jQuery(post_smtp_localize.postman_hostname_element_name).focus();
6
+ elHostname.click(function() {
7
+ valid = jQuery('#port_test_form_id').valid();
8
+ if (!valid) {
9
+ return false;
10
+ }
11
+
12
+ // initialize the view for a new test
13
+ elHostname.attr('disabled', 'disabled');
14
+ hide('#conclusion');
15
+ hide('#blocked-port-help');
16
+ jQuery('ol.conclusion').html('');
17
+ showLoaderIcon();
18
+
19
+ var $elTestingTable = jQuery('#connectivity_test_table');
20
+ $elTestingTable.show();
21
+ show('.portquiz');
22
+
23
+ var hostname = jQuery(post_smtp_localize.postman_hostname_element_name).val();
24
+ var data = {
25
+ 'action' : 'postman_get_hosts_to_test',
26
+ 'hostname' : hostname,
27
+ 'security' : jQuery('#security').val(),
28
+ };
29
+
30
+ totalPortsTested = 0;
31
+ portsToBeTested = 0;
32
+
33
+ jQuery.post(ajaxurl, data, function(response) {
34
+ if (postmanValidateAjaxResponseWithPopup(response)) {
35
+ handleHostsToCheckResponse(response.data);
36
+ }
37
+ }).fail(function(response) {
38
+ ajaxFailed(response);
39
+ });
40
+
41
+ //
42
+ return false;
43
+ });
44
+ });
45
+
46
+ /**
47
+ * Handles the response from the server of the list of sockets to check.
48
+ *
49
+ * @param hostname
50
+ * @param response
51
+ */
52
+ function handleHostsToCheckResponse(response) {
53
+ for ( var x in response.hosts) {
54
+ var id = response.hosts[x].id;
55
+ var transportSlug = response.hosts[x].transport_id;
56
+ var hostname = response.hosts[x].host;
57
+ var port = response.hosts[x].port
58
+ var cell = 'tr#' + id + " td.socket";
59
+ var testEl = jQuery(cell);
60
+ testEl.html('<span>' + hostname + ':' + port + '</span>');
61
+ portQuizTest(response.hosts[x], hostname, port);
62
+ }
63
+ }
64
+
65
+ function portQuizTest(socket, hostname, port) {
66
+ resetView(socket.id);
67
+ portsToBeTested += 1;
68
+ var cell = 'tr#' + socket.id + " td.firewall";
69
+ var testEl = jQuery(cell);
70
+ testEl.html('<span style="color:blue">' + postman_port_test.in_progress
71
+ + '</span>');
72
+ var data = {
73
+ 'action' : 'postman_port_quiz_test',
74
+ 'hostname' : hostname,
75
+ 'port' : port,
76
+ 'security' : jQuery('#security').val(),
77
+ };
78
+ jQuery.post(
79
+ ajaxurl,
80
+ data,
81
+ function(response) {
82
+ if (postmanValidateAjaxResponseWithPopup(response)) {
83
+ if (response.success) {
84
+ testEl.html('<span style="color:green">'
85
+ + postman_port_test.open + '</span>');
86
+ // start the next test
87
+ } else {
88
+ testEl.html('<span style="color:red">'
89
+ + postman_port_test.closed + '</span>');
90
+ }
91
+ firstServiceTest(socket, hostname, port, response.success);
92
+ }
93
+ }).fail(
94
+ function(response) {
95
+ totalPortsTested += 1;
96
+ testEl.html('<span style="color:red">'
97
+ + postman_email_test.ajax_error + "</span>");
98
+ enableButtonCheck();
99
+ });
100
+ }
101
+ function firstServiceTest(socket, hostname, port, open) {
102
+ var cell = 'tr#' + socket.id + " td.service";
103
+ var testEl = jQuery(cell);
104
+ testEl.html('<span style="color:blue">' + postman_port_test.in_progress
105
+ + '</span>');
106
+ var data = {
107
+ 'action' : 'postman_test_port',
108
+ 'hostname' : hostname,
109
+ 'port' : port,
110
+ 'security' : jQuery('#security').val(),
111
+ };
112
+ jQuery
113
+ .post(
114
+ ajaxurl,
115
+ data,
116
+ function(response) {
117
+ if (postmanValidateAjaxResponseWithPopup(response)) {
118
+ if (response.success) {
119
+ totalPortsTested += 1;
120
+ if (port == 443) {
121
+ // API test
122
+ testEl
123
+ .html('<span style="color:green">&#x1f512; '
124
+ + response.data.protocol
125
+ + '</span>');
126
+ var cell = 'tr#' + socket.id
127
+ + " td.reported_id";
128
+ var p443El = jQuery(cell);
129
+ if (response.data.reported_hostname_domain_only) {
130
+ p443El
131
+ .html('<span>'
132
+ + response.data.reported_hostname_domain_only
133
+ + '</span>');
134
+ }
135
+ addConclusion(sprintf(
136
+ postman_port_test.https_success,
137
+ response.data.port,
138
+ socket.transport_name), true,
139
+ response.data.secure);
140
+ } else {
141
+ // SMTP test
142
+ testEl.html('<span style="color:green">'
143
+ + response.data.protocol
144
+ + '</span>');
145
+ inspectResponse(socket.id, response.data,
146
+ port);
147
+ var message = sprintf(postman_port_test.success,
148
+ port, hostname);
149
+ if (response.data.mitm) {
150
+ message += ' <span style="background-color:yellow">'
151
+ + sprintf(
152
+ postman_port_test.mitm,
153
+ response.data.reported_hostname_domain_only,
154
+ response.data.hostname_domain_only)
155
+ + '</span>';
156
+ }
157
+ addConclusion(message, true,
158
+ response.data.secure);
159
+ }
160
+ } else {
161
+ if (port == 443) {
162
+ // API test
163
+ testEl.html('<span style="color:red">'
164
+ + postman_port_test.no + '</span>');
165
+ totalPortsTested += 1;
166
+ var p443El = jQuery(cell);
167
+ addConclusion(sprintf(postman_port_test.try_dif_smtp,
168
+ port, hostname), false,
169
+ response.data.secure);
170
+ } else {
171
+ if (response.data.try_smtps) {
172
+ // start the SMTPS test
173
+ portTest3(socket, hostname, port, open);
174
+ } else {
175
+ testEl.html('<span style="color:red">'
176
+ + postman_port_test.no + '</span>');
177
+ totalPortsTested += 1;
178
+ addConclusion(sprintf(
179
+ postman_port_test.blocked, port),
180
+ false, response.data.secure);
181
+ show('#blocked-port-help');
182
+ }
183
+ }
184
+ }
185
+ enableButtonCheck();
186
+ }
187
+ }).fail(
188
+ function(response) {
189
+ totalPortsTested += 1;
190
+ testEl.html('<span style="color:red">'
191
+ + postman_email_test.ajax_error + "</span>");
192
+ enableButtonCheck();
193
+ });
194
+ }
195
+ function portTest3(socket, hostname, port, open) {
196
+ var cell = 'tr#' + socket.id + " td.service";
197
+ var testEl = jQuery(cell);
198
+ testEl.html('<span style="color:blue">' + postman_port_test.in_progress
199
+ + '</span>');
200
+ var data = {
201
+ 'action' : 'postman_test_smtps',
202
+ 'hostname' : hostname,
203
+ 'port' : port,
204
+ 'security' : jQuery('#security').val(),
205
+ };
206
+ jQuery
207
+ .post(
208
+ ajaxurl,
209
+ data,
210
+ function(response) {
211
+ if (postmanValidateAjaxResponseWithPopup(response)) {
212
+ if (response.success) {
213
+ if (response.data.protocol == 'SMTPS') {
214
+ testEl
215
+ .html('<span style="color:green">&#x1f512; '
216
+ + response.data.protocol
217
+ + '</span>');
218
+ } else {
219
+
220
+ testEl.html('<span style="color:green">'
221
+ + response.data.protocol
222
+ + '</span>');
223
+ }
224
+ inspectResponse(socket.id, response.data, port);
225
+ var message = sprintf(postman_port_test.success,
226
+ port, hostname);
227
+ if (response.data.mitm) {
228
+ message += ' <span style="background-color:yellow">'
229
+ + sprintf(
230
+ postman_port_test.mitm,
231
+ response.data.reported_hostname_domain_only,
232
+ response.data.hostname_domain_only
233
+ + '</span>');
234
+ }
235
+ addConclusion(message, true,
236
+ response.data.secure);
237
+ } else {
238
+ testEl.html('<span style="color:red">'
239
+ + postman_port_test.no + '</span>');
240
+ show('#blocked-port-help');
241
+ if (open) {
242
+ addConclusion(sprintf(postman_port_test.try_dif_smtp,
243
+ port, hostname), false,
244
+ response.data.secure);
245
+ } else {
246
+ addConclusion(sprintf(postman_port_test.blocked,
247
+ port), false, response.data.secure);
248
+ }
249
+ }
250
+ totalPortsTested += 1;
251
+ enableButtonCheck();
252
+ }
253
+ }).fail(
254
+ function(response) {
255
+ totalPortsTested += 1;
256
+ testEl.html('<span style="color:red">'
257
+ + postman_email_test.ajax_error + "</span>");
258
+ enableButtonCheck();
259
+ });
260
+ }
261
+ function enableButtonCheck() {
262
+ if (totalPortsTested >= portsToBeTested) {
263
+ enable(postman_begin_test_button_id);
264
+ hideLoaderIcon();
265
+ jQuery(post_smtp_localize.postman_hostname_element_name).focus();
266
+ }
267
+ }
268
+ function inspectResponse(id, response, port) {
269
+ var cell = 'tr#' + id + " td.reported_id";
270
+ var testEl = jQuery(cell);
271
+ if (response.reported_hostname_domain_only) {
272
+ testEl.html('<span>' + response.reported_hostname_domain_only
273
+ + '</span>');
274
+ }
275
+ var cell = 'tr#' + id + " td.service";
276
+ var testEl = jQuery(cell);
277
+ if (response.protocol == 'SMTPS') {
278
+ testEl.html('<span style="color:green">&#x1f512; SMTPS</span>');
279
+ } else if (response.start_tls) {
280
+ testEl.html('<span style="color:green">&#x1f512; SMTP-STARTTLS</span>');
281
+ } else {
282
+ testEl.html('<span style="color:green">SMTP</span>');
283
+ }
284
+ var cell = 'tr#' + id + " td.auth_none";
285
+ var testEl = jQuery(cell);
286
+ if (response.auth_none) {
287
+ testEl.html('<span style="color:green">' + postman_port_test.yes + '</span>');
288
+ } else {
289
+ testEl.html('<span>' + postman_port_test.no + '</span>');
290
+ }
291
+ var cell = 'tr#' + id + " td.auth_plain";
292
+ var testEl = jQuery(cell);
293
+ if (response.auth_plain) {
294
+ testEl.html('<span style="color:green">' + postman_port_test.yes + '</span>');
295
+ } else {
296
+ testEl.html('<span>' + postman_port_test.no + '</span>');
297
+ }
298
+ var cell = 'tr#' + id + " td.auth_login";
299
+ var testEl = jQuery(cell);
300
+ if (response.auth_login) {
301
+ testEl.html('<span style="color:green">' + postman_port_test.yes + '</span>');
302
+ } else {
303
+ testEl.html('<span>' + postman_port_test.no + '</span>');
304
+ }
305
+ var cell = 'tr#' + id + " td.auth_crammd5";
306
+ var testEl = jQuery(cell);
307
+ if (response.auth_crammd5) {
308
+ testEl.html('<span style="color:green">' + postman_port_test.yes + '</span>');
309
+ } else {
310
+ testEl.html('<span>' + postman_port_test.no + '</span>');
311
+ }
312
+ var cell = 'tr#' + id + " td.auth_xoauth2";
313
+ var testEl = jQuery(cell);
314
+ if (response.auth_xoauth) {
315
+ testEl.html('<span style="color:green">' + postman_port_test.yes + '</span>');
316
+ } else {
317
+ testEl.html('<span>' + postman_port_test.no + '</span>');
318
+ }
319
+ }
320
+ function resetView(id) {
321
+ var testEl = jQuery('tr#' + id + ' td.resettable');
322
+ testEl.html('-');
323
+ }
324
+ function addConclusion(message, success, isSecure) {
325
+ show('#conclusion');
326
+ var secureIcon = '';
327
+ if (isSecure) {
328
+ secureIcon = '&#x1f512; ';
329
+ }
330
+ if (success) {
331
+ message = '&#9989; ' + secureIcon + message;
332
+ } else {
333
+ message = '&#10060; ' + secureIcon + message;
334
+ }
335
+ jQuery('ol.conclusion').append('<li>' + message + '</li>');
336
+ }
Postman/Postman-Connectivity-Test/registered-domain-libs-master/PHP/effectiveTLDs.inc.php CHANGED
@@ -1,6484 +1,6484 @@
1
- <?php
2
- // This Source Code Form is subject to the terms of the Mozilla Public
3
- // License, v. 2.0. If a copy of the MPL was not distributed with this
4
- // file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
-
6
- $tldTree = array('ac' => array('com' => array(),
7
- 'edu' => array(),
8
- 'gov' => array(),
9
- 'net' => array(),
10
- 'mil' => array(),
11
- 'org' => array()),
12
- 'ad' => array('nom' => array()),
13
- 'ae' => array('co' => array(),
14
- 'net' => array(),
15
- 'org' => array(),
16
- 'sch' => array(),
17
- 'ac' => array(),
18
- 'gov' => array(),
19
- 'mil' => array()),
20
- 'aero' => array('accident-investigation' => array(),
21
- 'accident-prevention' => array(),
22
- 'aerobatic' => array(),
23
- 'aeroclub' => array(),
24
- 'aerodrome' => array(),
25
- 'agents' => array(),
26
- 'aircraft' => array(),
27
- 'airline' => array(),
28
- 'airport' => array(),
29
- 'air-surveillance' => array(),
30
- 'airtraffic' => array(),
31
- 'air-traffic-control' => array(),
32
- 'ambulance' => array(),
33
- 'amusement' => array(),
34
- 'association' => array(),
35
- 'author' => array(),
36
- 'ballooning' => array(),
37
- 'broker' => array(),
38
- 'caa' => array(),
39
- 'cargo' => array(),
40
- 'catering' => array(),
41
- 'certification' => array(),
42
- 'championship' => array(),
43
- 'charter' => array(),
44
- 'civilaviation' => array(),
45
- 'club' => array(),
46
- 'conference' => array(),
47
- 'consultant' => array(),
48
- 'consulting' => array(),
49
- 'control' => array(),
50
- 'council' => array(),
51
- 'crew' => array(),
52
- 'design' => array(),
53
- 'dgca' => array(),
54
- 'educator' => array(),
55
- 'emergency' => array(),
56
- 'engine' => array(),
57
- 'engineer' => array(),
58
- 'entertainment' => array(),
59
- 'equipment' => array(),
60
- 'exchange' => array(),
61
- 'express' => array(),
62
- 'federation' => array(),
63
- 'flight' => array(),
64
- 'freight' => array(),
65
- 'fuel' => array(),
66
- 'gliding' => array(),
67
- 'government' => array(),
68
- 'groundhandling' => array(),
69
- 'group' => array(),
70
- 'hanggliding' => array(),
71
- 'homebuilt' => array(),
72
- 'insurance' => array(),
73
- 'journal' => array(),
74
- 'journalist' => array(),
75
- 'leasing' => array(),
76
- 'logistics' => array(),
77
- 'magazine' => array(),
78
- 'maintenance' => array(),
79
- 'marketplace' => array(),
80
- 'media' => array(),
81
- 'microlight' => array(),
82
- 'modelling' => array(),
83
- 'navigation' => array(),
84
- 'parachuting' => array(),
85
- 'paragliding' => array(),
86
- 'passenger-association' => array(),
87
- 'pilot' => array(),
88
- 'press' => array(),
89
- 'production' => array(),
90
- 'recreation' => array(),
91
- 'repbody' => array(),
92
- 'res' => array(),
93
- 'research' => array(),
94
- 'rotorcraft' => array(),
95
- 'safety' => array(),
96
- 'scientist' => array(),
97
- 'services' => array(),
98
- 'show' => array(),
99
- 'skydiving' => array(),
100
- 'software' => array(),
101
- 'student' => array(),
102
- 'taxi' => array(),
103
- 'trader' => array(),
104
- 'trading' => array(),
105
- 'trainer' => array(),
106
- 'union' => array(),
107
- 'workinggroup' => array(),
108
- 'works' => array()),
109
- 'af' => array('gov' => array(),
110
- 'com' => array(),
111
- 'org' => array(),
112
- 'net' => array(),
113
- 'edu' => array()),
114
- 'ag' => array('com' => array(),
115
- 'org' => array(),
116
- 'net' => array(),
117
- 'co' => array(),
118
- 'nom' => array()),
119
- 'ai' => array('off' => array(),
120
- 'com' => array(),
121
- 'net' => array(),
122
- 'org' => array()),
123
- 'al' => array('com' => array(),
124
- 'edu' => array(),
125
- 'gov' => array(),
126
- 'mil' => array(),
127
- 'net' => array(),
128
- 'org' => array()),
129
- 'am' => array(),
130
- 'an' => array('com' => array(),
131
- 'net' => array(),
132
- 'org' => array(),
133
- 'edu' => array()),
134
- 'ao' => array('ed' => array(),
135
- 'gv' => array(),
136
- 'og' => array(),
137
- 'co' => array(),
138
- 'pb' => array(),
139
- 'it' => array()),
140
- 'aq' => array(),
141
- 'ar' => array('com' => array('blogspot' => array()),
142
- 'edu' => array(),
143
- 'gob' => array(),
144
- 'gov' => array(),
145
- 'int' => array(),
146
- 'mil' => array(),
147
- 'net' => array(),
148
- 'org' => array(),
149
- 'tur' => array()),
150
- 'arpa' => array('e164' => array(),
151
- 'in-addr' => array(),
152
- 'ip6' => array(),
153
- 'iris' => array(),
154
- 'uri' => array(),
155
- 'urn' => array()),
156
- 'as' => array('gov' => array()),
157
- 'asia' => array(),
158
- 'at' => array('ac' => array(),
159
- 'co' => array('blogspot' => array()),
160
- 'gv' => array(),
161
- 'or' => array(),
162
- 'biz' => array(),
163
- 'info' => array(),
164
- 'priv' => array()),
165
- 'au' => array('com' => array('blogspot' => array()),
166
- 'net' => array(),
167
- 'org' => array(),
168
- 'edu' => array('act' => array(),
169
- 'nsw' => array(),
170
- 'nt' => array(),
171
- 'qld' => array(),
172
- 'sa' => array(),
173
- 'tas' => array(),
174
- 'vic' => array(),
175
- 'wa' => array()),
176
- 'gov' => array('qld' => array(),
177
- 'sa' => array(),
178
- 'tas' => array(),
179
- 'vic' => array(),
180
- 'wa' => array()),
181
- 'asn' => array(),
182
- 'id' => array(),
183
- 'info' => array(),
184
- 'conf' => array(),
185
- 'oz' => array(),
186
- 'act' => array(),
187
- 'nsw' => array(),
188
- 'nt' => array(),
189
- 'qld' => array(),
190
- 'sa' => array(),
191
- 'tas' => array(),
192
- 'vic' => array(),
193
- 'wa' => array()),
194
- 'aw' => array('com' => array()),
195
- 'ax' => array(),
196
- 'az' => array('com' => array(),
197
- 'net' => array(),
198
- 'int' => array(),
199
- 'gov' => array(),
200
- 'org' => array(),
201
- 'edu' => array(),
202
- 'info' => array(),
203
- 'pp' => array(),
204
- 'mil' => array(),
205
- 'name' => array(),
206
- 'pro' => array(),
207
- 'biz' => array()),
208
- 'ba' => array('org' => array(),
209
- 'net' => array(),
210
- 'edu' => array(),
211
- 'gov' => array(),
212
- 'mil' => array(),
213
- 'unsa' => array(),
214
- 'unbi' => array(),
215
- 'co' => array(),
216
- 'com' => array(),
217
- 'rs' => array()),
218
- 'bb' => array('biz' => array(),
219
- 'co' => array(),
220
- 'com' => array(),
221
- 'edu' => array(),
222
- 'gov' => array(),
223
- 'info' => array(),
224
- 'net' => array(),
225
- 'org' => array(),
226
- 'store' => array(),
227
- 'tv' => array()),
228
- 'bd' => array('*' => array()),
229
- 'be' => array('ac' => array(),
230
- 'blogspot' => array()),
231
- 'bf' => array('gov' => array()),
232
- 'bg' => array('a' => array(),
233
- 'b' => array(),
234
- 'c' => array(),
235
- 'd' => array(),
236
- 'e' => array(),
237
- 'f' => array(),
238
- 'g' => array(),
239
- 'h' => array(),
240
- 'i' => array(),
241
- 'j' => array(),
242
- 'k' => array(),
243
- 'l' => array(),
244
- 'm' => array(),
245
- 'n' => array(),
246
- 'o' => array(),
247
- 'p' => array(),
248
- 'q' => array(),
249
- 'r' => array(),
250
- 's' => array(),
251
- 't' => array(),
252
- 'u' => array(),
253
- 'v' => array(),
254
- 'w' => array(),
255
- 'x' => array(),
256
- 'y' => array(),
257
- 'z' => array(),
258
- '0' => array(),
259
- '1' => array(),
260
- '2' => array(),
261
- '3' => array(),
262
- '4' => array(),
263
- '5' => array(),
264
- '6' => array(),
265
- '7' => array(),
266
- '8' => array(),
267
- '9' => array()),
268
- 'bh' => array('com' => array(),
269
- 'edu' => array(),
270
- 'net' => array(),
271
- 'org' => array(),
272
- 'gov' => array()),
273
- 'bi' => array('co' => array(),
274
- 'com' => array(),
275
- 'edu' => array(),
276
- 'or' => array(),
277
- 'org' => array()),
278
- 'biz' => array('dyndns' => array(),
279
- 'for-better' => array(),
280
- 'for-more' => array(),
281
- 'for-some' => array(),
282
- 'for-the' => array(),
283
- 'selfip' => array(),
284
- 'webhop' => array()),
285
- 'bj' => array('asso' => array(),
286
- 'barreau' => array(),
287
- 'gouv' => array(),
288
- 'blogspot' => array()),
289
- 'bm' => array('com' => array(),
290
- 'edu' => array(),
291
- 'gov' => array(),
292
- 'net' => array(),
293
- 'org' => array()),
294
- 'bn' => array('*' => array()),
295
- 'bo' => array('com' => array(),
296
- 'edu' => array(),
297
- 'gov' => array(),
298
- 'gob' => array(),
299
- 'int' => array(),
300
- 'org' => array(),
301
- 'net' => array(),
302
- 'mil' => array(),
303
- 'tv' => array()),
304
- 'br' => array('adm' => array(),
305
- 'adv' => array(),
306
- 'agr' => array(),
307
- 'am' => array(),
308
- 'arq' => array(),
309
- 'art' => array(),
310
- 'ato' => array(),
311
- 'b' => array(),
312
- 'bio' => array(),
313
- 'blog' => array(),
314
- 'bmd' => array(),
315
- 'cim' => array(),
316
- 'cng' => array(),
317
- 'cnt' => array(),
318
- 'com' => array('blogspot' => array()),
319
- 'coop' => array(),
320
- 'ecn' => array(),
321
- 'eco' => array(),
322
- 'edu' => array(),
323
- 'emp' => array(),
324
- 'eng' => array(),
325
- 'esp' => array(),
326
- 'etc' => array(),
327
- 'eti' => array(),
328
- 'far' => array(),
329
- 'flog' => array(),
330
- 'fm' => array(),
331
- 'fnd' => array(),
332
- 'fot' => array(),
333
- 'fst' => array(),
334
- 'g12' => array(),
335
- 'ggf' => array(),
336
- 'gov' => array(),
337
- 'imb' => array(),
338
- 'ind' => array(),
339
- 'inf' => array(),
340
- 'jor' => array(),
341
- 'jus' => array(),
342
- 'leg' => array(),
343
- 'lel' => array(),
344
- 'mat' => array(),
345
- 'med' => array(),
346
- 'mil' => array(),
347
- 'mp' => array(),
348
- 'mus' => array(),
349
- 'net' => array(),
350
- 'nom' => array('*' => array()),
351
- 'not' => array(),
352
- 'ntr' => array(),
353
- 'odo' => array(),
354
- 'org' => array(),
355
- 'ppg' => array(),
356
- 'pro' => array(),
357
- 'psc' => array(),
358
- 'psi' => array(),
359
- 'qsl' => array(),
360
- 'radio' => array(),
361
- 'rec' => array(),
362
- 'slg' => array(),
363
- 'srv' => array(),
364
- 'taxi' => array(),
365
- 'teo' => array(),
366
- 'tmp' => array(),
367
- 'trd' => array(),
368
- 'tur' => array(),
369
- 'tv' => array(),
370
- 'vet' => array(),
371
- 'vlog' => array(),
372
- 'wiki' => array(),
373
- 'zlg' => array()),
374
- 'bs' => array('com' => array(),
375
- 'net' => array(),
376
- 'org' => array(),
377
- 'edu' => array(),
378
- 'gov' => array()),
379
- 'bt' => array('com' => array(),
380
- 'edu' => array(),
381
- 'gov' => array(),
382
- 'net' => array(),
383
- 'org' => array()),
384
- 'bv' => array(),
385
- 'bw' => array('co' => array(),
386
- 'org' => array()),
387
- 'by' => array('gov' => array(),
388
- 'mil' => array(),
389
- 'com' => array(),
390
- 'of' => array()),
391
- 'bz' => array('com' => array(),
392
- 'net' => array(),
393
- 'org' => array(),
394
- 'edu' => array(),
395
- 'gov' => array(),
396
- 'za' => array()),
397
- 'ca' => array('ab' => array(),
398
- 'bc' => array(),
399
- 'mb' => array(),
400
- 'nb' => array(),
401
- 'nf' => array(),
402
- 'nl' => array(),
403
- 'ns' => array(),
404
- 'nt' => array(),
405
- 'nu' => array(),
406
- 'on' => array(),
407
- 'pe' => array(),
408
- 'qc' => array(),
409
- 'sk' => array(),
410
- 'yk' => array(),
411
- 'gc' => array(),
412
- 'co' => array(),
413
- 'blogspot' => array()),
414
- 'cat' => array(),
415
- 'cc' => array('ftpaccess' => array(),
416
- 'game-server' => array(),
417
- 'myphotos' => array(),
418
- 'scrapping' => array()),
419
- 'cd' => array('gov' => array()),
420
- 'cf' => array('blogspot' => array()),
421
- 'cg' => array(),
422
- 'ch' => array('blogspot' => array()),
423
- 'ci' => array('org' => array(),
424
- 'or' => array(),
425
- 'com' => array(),
426
- 'co' => array(),
427
- 'edu' => array(),
428
- 'ed' => array(),
429
- 'ac' => array(),
430
- 'net' => array(),
431
- 'go' => array(),
432
- 'asso' => array(),
433
- 'aéroport' => array(),
434
- 'int' => array(),
435
- 'presse' => array(),
436
- 'md' => array(),
437
- 'gouv' => array()),
438
- 'ck' => array('*' => array(),
439
- 'www' => array('!' => '')),
440
- 'cl' => array('gov' => array(),
441
- 'gob' => array(),
442
- 'co' => array(),
443
- 'mil' => array()),
444
- 'cm' => array('co' => array(),
445
- 'com' => array(),
446
- 'gov' => array(),
447
- 'net' => array()),
448
- 'cn' => array('ac' => array(),
449
- 'com' => array(),
450
- 'edu' => array(),
451
- 'gov' => array(),
452
- 'net' => array(),
453
- 'org' => array(),
454
- 'mil' => array(),
455
- '公司' => array(),
456
- '网络' => array(),
457
- '網絡' => array(),
458
- 'ah' => array(),
459
- 'bj' => array(),
460
- 'cq' => array(),
461
- 'fj' => array(),
462
- 'gd' => array(),
463
- 'gs' => array(),
464
- 'gz' => array(),
465
- 'gx' => array(),
466
- 'ha' => array(),
467
- 'hb' => array(),
468
- 'he' => array(),
469
- 'hi' => array(),
470
- 'hl' => array(),
471
- 'hn' => array(),
472
- 'jl' => array(),
473
- 'js' => array(),
474
- 'jx' => array(),
475
- 'ln' => array(),
476
- 'nm' => array(),
477
- 'nx' => array(),
478
- 'qh' => array(),
479
- 'sc' => array(),
480
- 'sd' => array(),
481
- 'sh' => array(),
482
- 'sn' => array(),
483
- 'sx' => array(),
484
- 'tj' => array(),
485
- 'xj' => array(),
486
- 'xz' => array(),
487
- 'yn' => array(),
488
- 'zj' => array(),
489
- 'hk' => array(),
490
- 'mo' => array(),
491
- 'tw' => array(),
492
- 'amazonaws' => array('compute' => array('cn-north-1' => array()))),
493
- 'co' => array('arts' => array(),
494
- 'com' => array(),
495
- 'edu' => array(),
496
- 'firm' => array(),
497
- 'gov' => array(),
498
- 'info' => array(),
499
- 'int' => array(),
500
- 'mil' => array(),
501
- 'net' => array(),
502
- 'nom' => array(),
503
- 'org' => array(),
504
- 'rec' => array(),
505
- 'web' => array()),
506
- 'com' => array('amazonaws' => array('compute' => array('ap-northeast-1' => array(),
507
- 'ap-southeast-1' => array(),
508
- 'ap-southeast-2' => array(),
509
- 'eu-west-1' => array(),
510
- 'sa-east-1' => array(),
511
- 'us-gov-west-1' => array(),
512
- 'us-west-1' => array(),
513
- 'us-west-2' => array()),
514
- 'compute-1' => array('z-1' => array(),
515
- 'z-2' => array()),
516
- 'us-east-1' => array(),
517
- 'elb' => array(),
518
- 's3' => array(),
519
- 's3-us-west-2' => array(),
520
- 's3-us-west-1' => array(),
521
- 's3-eu-west-1' => array(),
522
- 's3-ap-southeast-1' => array(),
523
- 's3-ap-southeast-2' => array(),
524
- 's3-ap-northeast-1' => array(),
525
- 's3-sa-east-1' => array(),
526
- 's3-us-gov-west-1' => array(),
527
- 's3-fips-us-gov-west-1' => array(),
528
- 's3-website-us-east-1' => array(),
529
- 's3-website-us-west-2' => array(),
530
- 's3-website-us-west-1' => array(),
531
- 's3-website-eu-west-1' => array(),
532
- 's3-website-ap-southeast-1' => array(),
533
- 's3-website-ap-southeast-2' => array(),
534
- 's3-website-ap-northeast-1' => array(),
535
- 's3-website-sa-east-1' => array(),
536
- 's3-website-us-gov-west-1' => array()),
537
- 'elasticbeanstalk' => array(),
538
- 'betainabox' => array(),
539
- 'ar' => array(),
540
- 'br' => array(),
541
- 'cn' => array(),
542
- 'de' => array(),
543
- 'eu' => array(),
544
- 'gb' => array(),
545
- 'hu' => array(),
546
- 'jpn' => array(),
547
- 'kr' => array(),
548
- 'mex' => array(),
549
- 'no' => array(),
550
- 'qc' => array(),
551
- 'ru' => array(),
552
- 'sa' => array(),
553
- 'se' => array(),
554
- 'uk' => array(),
555
- 'us' => array(),
556
- 'uy' => array(),
557
- 'za' => array(),
558
- 'africa' => array(),
559
- 'gr' => array(),
560
- 'co' => array(),
561
- 'cloudcontrolled' => array(),
562
- 'cloudcontrolapp' => array(),
563
- 'dreamhosters' => array(),
564
- 'dyndns-at-home' => array(),
565
- 'dyndns-at-work' => array(),
566
- 'dyndns-blog' => array(),
567
- 'dyndns-free' => array(),
568
- 'dyndns-home' => array(),
569
- 'dyndns-ip' => array(),
570
- 'dyndns-mail' => array(),
571
- 'dyndns-office' => array(),
572
- 'dyndns-pics' => array(),
573
- 'dyndns-remote' => array(),
574
- 'dyndns-server' => array(),
575
- 'dyndns-web' => array(),
576
- 'dyndns-wiki' => array(),
577
- 'dyndns-work' => array(),
578
- 'blogdns' => array(),
579
- 'cechire' => array(),
580
- 'dnsalias' => array(),
581
- 'dnsdojo' => array(),
582
- 'doesntexist' => array(),
583
- 'dontexist' => array(),
584
- 'doomdns' => array(),
585
- 'dyn-o-saur' => array(),
586
- 'dynalias' => array(),
587
- 'est-a-la-maison' => array(),
588
- 'est-a-la-masion' => array(),
589
- 'est-le-patron' => array(),
590
- 'est-mon-blogueur' => array(),
591
- 'from-ak' => array(),
592
- 'from-al' => array(),
593
- 'from-ar' => array(),
594
- 'from-ca' => array(),
595
- 'from-ct' => array(),
596
- 'from-dc' => array(),
597
- 'from-de' => array(),
598
- 'from-fl' => array(),
599
- 'from-ga' => array(),
600
- 'from-hi' => array(),
601
- 'from-ia' => array(),
602
- 'from-id' => array(),
603
- 'from-il' => array(),
604
- 'from-in' => array(),
605
- 'from-ks' => array(),
606
- 'from-ky' => array(),
607
- 'from-ma' => array(),
608
- 'from-md' => array(),
609
- 'from-mi' => array(),
610
- 'from-mn' => array(),
611
- 'from-mo' => array(),
612
- 'from-ms' => array(),
613
- 'from-mt' => array(),
614
- 'from-nc' => array(),
615
- 'from-nd' => array(),
616
- 'from-ne' => array(),
617
- 'from-nh' => array(),
618
- 'from-nj' => array(),
619
- 'from-nm' => array(),
620
- 'from-nv' => array(),
621
- 'from-oh' => array(),
622
- 'from-ok' => array(),
623
- 'from-or' => array(),
624
- 'from-pa' => array(),
625
- 'from-pr' => array(),
626
- 'from-ri' => array(),
627
- 'from-sc' => array(),
628
- 'from-sd' => array(),
629
- 'from-tn' => array(),
630
- 'from-tx' => array(),
631
- 'from-ut' => array(),
632
- 'from-va' => array(),
633
- 'from-vt' => array(),
634
- 'from-wa' => array(),
635
- 'from-wi' => array(),
636
- 'from-wv' => array(),
637
- 'from-wy' => array(),
638
- 'getmyip' => array(),
639
- 'gotdns' => array(),
640
- 'hobby-site' => array(),
641
- 'homelinux' => array(),
642
- 'homeunix' => array(),
643
- 'iamallama' => array(),
644
- 'is-a-anarchist' => array(),
645
- 'is-a-blogger' => array(),
646
- 'is-a-bookkeeper' => array(),
647
- 'is-a-bulls-fan' => array(),
648
- 'is-a-caterer' => array(),
649
- 'is-a-chef' => array(),
650
- 'is-a-conservative' => array(),
651
- 'is-a-cpa' => array(),
652
- 'is-a-cubicle-slave' => array(),
653
- 'is-a-democrat' => array(),
654
- 'is-a-designer' => array(),
655
- 'is-a-doctor' => array(),
656
- 'is-a-financialadvisor' => array(),
657
- 'is-a-geek' => array(),
658
- 'is-a-green' => array(),
659
- 'is-a-guru' => array(),
660
- 'is-a-hard-worker' => array(),
661
- 'is-a-hunter' => array(),
662
- 'is-a-landscaper' => array(),
663
- 'is-a-lawyer' => array(),
664
- 'is-a-liberal' => array(),
665
- 'is-a-libertarian' => array(),
666
- 'is-a-llama' => array(),
667
- 'is-a-musician' => array(),
668
- 'is-a-nascarfan' => array(),
669
- 'is-a-nurse' => array(),
670
- 'is-a-painter' => array(),
671
- 'is-a-personaltrainer' => array(),
672
- 'is-a-photographer' => array(),
673
- 'is-a-player' => array(),
674
- 'is-a-republican' => array(),
675
- 'is-a-rockstar' => array(),
676
- 'is-a-socialist' => array(),
677
- 'is-a-student' => array(),
678
- 'is-a-teacher' => array(),
679
- 'is-a-techie' => array(),
680
- 'is-a-therapist' => array(),
681
- 'is-an-accountant' => array(),
682
- 'is-an-actor' => array(),
683
- 'is-an-actress' => array(),
684
- 'is-an-anarchist' => array(),
685
- 'is-an-artist' => array(),
686
- 'is-an-engineer' => array(),
687
- 'is-an-entertainer' => array(),
688
- 'is-certified' => array(),
689
- 'is-gone' => array(),
690
- 'is-into-anime' => array(),
691
- 'is-into-cars' => array(),
692
- 'is-into-cartoons' => array(),
693
- 'is-into-games' => array(),
694
- 'is-leet' => array(),
695
- 'is-not-certified' => array(),
696
- 'is-slick' => array(),
697
- 'is-uberleet' => array(),
698
- 'is-with-theband' => array(),
699
- 'isa-geek' => array(),
700
- 'isa-hockeynut' => array(),
701
- 'issmarterthanyou' => array(),
702
- 'likes-pie' => array(),
703
- 'likescandy' => array(),
704
- 'neat-url' => array(),
705
- 'saves-the-whales' => array(),
706
- 'selfip' => array(),
707
- 'sells-for-less' => array(),
708
- 'sells-for-u' => array(),
709
- 'servebbs' => array(),
710
- 'simple-url' => array(),
711
- 'space-to-rent' => array(),
712
- 'teaches-yoga' => array(),
713
- 'writesthisblog' => array(),
714
- 'firebaseapp' => array(),
715
- 'flynnhub' => array(),
716
- 'githubusercontent' => array(),
717
- 'ro' => array(),
718
- 'appspot' => array(),
719
- 'blogspot' => array(),
720
- 'codespot' => array(),
721
- 'googleapis' => array(),
722
- 'googlecode' => array(),
723
- 'withgoogle' => array(),
724
- 'herokuapp' => array(),
725
- 'herokussl' => array(),
726
- 'nfshost' => array(),
727
- 'operaunite' => array(),
728
- 'outsystemscloud' => array(),
729
- 'rhcloud' => array(),
730
- 'yolasite' => array()),
731
- 'coop' => array(),
732
- 'cr' => array('ac' => array(),
733
- 'co' => array(),
734
- 'ed' => array(),
735
- 'fi' => array(),
736
- 'go' => array(),
737
- 'or' => array(),
738
- 'sa' => array()),
739
- 'cu' => array('com' => array(),
740
- 'edu' => array(),
741
- 'org' => array(),
742
- 'net' => array(),
743
- 'gov' => array(),
744
- 'inf' => array()),
745
- 'cv' => array('blogspot' => array()),
746
- 'cw' => array('com' => array(),
747
- 'edu' => array(),
748
- 'net' => array(),
749
- 'org' => array()),
750
- 'cx' => array('gov' => array(),
751
- 'ath' => array()),
752
- 'cy' => array('*' => array()),
753
- 'cz' => array('blogspot' => array()),
754
- 'de' => array('com' => array(),
755
- 'fuettertdasnetz' => array(),
756
- 'isteingeek' => array(),
757
- 'istmein' => array(),
758
- 'lebtimnetz' => array(),
759
- 'leitungsen' => array(),
760
- 'traeumtgerade' => array(),
761
- 'blogspot' => array()),
762
- 'dj' => array(),
763
- 'dk' => array('blogspot' => array()),
764
- 'dm' => array('com' => array(),
765
- 'net' => array(),
766
- 'org' => array(),
767
- 'edu' => array(),
768
- 'gov' => array()),
769
- 'do' => array('art' => array(),
770
- 'com' => array(),
771
- 'edu' => array(),
772
- 'gob' => array(),
773
- 'gov' => array(),
774
- 'mil' => array(),
775
- 'net' => array(),
776
- 'org' => array(),
777
- 'sld' => array(),
778
- 'web' => array()),
779
- 'dz' => array('com' => array(),
780
- 'org' => array(),
781
- 'net' => array(),
782
- 'gov' => array(),
783
- 'edu' => array(),
784
- 'asso' => array(),
785
- 'pol' => array(),
786
- 'art' => array()),
787
- 'ec' => array('com' => array(),
788
- 'info' => array(),
789
- 'net' => array(),
790
- 'fin' => array(),
791
- 'k12' => array(),
792
- 'med' => array(),
793
- 'pro' => array(),
794
- 'org' => array(),
795
- 'edu' => array(),
796
- 'gov' => array(),
797
- 'gob' => array(),
798
- 'mil' => array()),
799
- 'edu' => array(),
800
- 'ee' => array('edu' => array(),
801
- 'gov' => array(),
802
- 'riik' => array(),
803
- 'lib' => array(),
804
- 'med' => array(),
805
- 'com' => array(),
806
- 'pri' => array(),
807
- 'aip' => array(),
808
- 'org' => array(),
809
- 'fie' => array()),
810
- 'eg' => array('com' => array(),
811
- 'edu' => array(),
812
- 'eun' => array(),
813
- 'gov' => array(),
814
- 'mil' => array(),
815
- 'name' => array(),
816
- 'net' => array(),
817
- 'org' => array(),
818
- 'sci' => array()),
819
- 'er' => array('*' => array()),
820
- 'es' => array('com' => array('blogspot' => array()),
821
- 'nom' => array(),
822
- 'org' => array(),
823
- 'gob' => array(),
824
- 'edu' => array()),
825
- 'et' => array('com' => array(),
826
- 'gov' => array(),
827
- 'org' => array(),
828
- 'edu' => array(),
829
- 'biz' => array(),
830
- 'name' => array(),
831
- 'info' => array()),
832
- 'eu' => array(),
833
- 'fi' => array('aland' => array(),
834
- 'blogspot' => array(),
835
- 'iki' => array()),
836
- 'fj' => array('*' => array()),
837
- 'fk' => array('*' => array()),
838
- 'fm' => array(),
839
- 'fo' => array(),
840
- 'fr' => array('com' => array(),
841
- 'asso' => array(),
842
- 'nom' => array(),
843
- 'prd' => array(),
844
- 'presse' => array(),
845
- 'tm' => array(),
846
- 'aeroport' => array(),
847
- 'assedic' => array(),
848
- 'avocat' => array(),
849
- 'avoues' => array(),
850
- 'cci' => array(),
851
- 'chambagri' => array(),
852
- 'chirurgiens-dentistes' => array(),
853
- 'experts-comptables' => array(),
854
- 'geometre-expert' => array(),
855
- 'gouv' => array(),
856
- 'greta' => array(),
857
- 'huissier-justice' => array(),
858
- 'medecin' => array(),
859
- 'notaires' => array(),
860
- 'pharmacien' => array(),
861
- 'port' => array(),
862
- 'veterinaire' => array(),
863
- 'blogspot' => array()),
864
- 'ga' => array(),
865
- 'gb' => array(),
866
- 'gd' => array(),
867
- 'ge' => array('com' => array(),
868
- 'edu' => array(),
869
- 'gov' => array(),
870
- 'org' => array(),
871
- 'mil' => array(),
872
- 'net' => array(),
873
- 'pvt' => array()),
874
- 'gf' => array(),
875
- 'gg' => array('co' => array(),
876
- 'net' => array(),
877
- 'org' => array()),
878
- 'gh' => array('com' => array(),
879
- 'edu' => array(),
880
- 'gov' => array(),
881
- 'org' => array(),
882
- 'mil' => array()),
883
- 'gi' => array('com' => array(),
884
- 'ltd' => array(),
885
- 'gov' => array(),
886
- 'mod' => array(),
887
- 'edu' => array(),
888
- 'org' => array()),
889
- 'gl' => array(),
890
- 'gm' => array(),
891
- 'gn' => array('ac' => array(),
892
- 'com' => array(),
893
- 'edu' => array(),
894
- 'gov' => array(),
895
- 'org' => array(),
896
- 'net' => array()),
897
- 'gov' => array(),
898
- 'gp' => array('com' => array(),
899
- 'net' => array(),
900
- 'mobi' => array(),
901
- 'edu' => array(),
902
- 'org' => array(),
903
- 'asso' => array()),
904
- 'gq' => array(),
905
- 'gr' => array('com' => array(),
906
- 'edu' => array(),
907
- 'net' => array(),
908
- 'org' => array(),
909
- 'gov' => array(),
910
- 'blogspot' => array()),
911
- 'gs' => array(),
912
- 'gt' => array('com' => array(),
913
- 'edu' => array(),
914
- 'gob' => array(),
915
- 'ind' => array(),
916
- 'mil' => array(),
917
- 'net' => array(),
918
- 'org' => array()),
919
- 'gu' => array('*' => array()),
920
- 'gw' => array(),
921
- 'gy' => array('co' => array(),
922
- 'com' => array(),
923
- 'net' => array()),
924
- 'hk' => array('com' => array(),
925
- 'edu' => array(),
926
- 'gov' => array(),
927
- 'idv' => array(),
928
- 'net' => array(),
929
- 'org' => array(),
930
- '公司' => array(),
931
- '教育' => array(),
932
- '敎育' => array(),
933
- '政府' => array(),
934
- '個人' => array(),
935
- '个人' => array(),
936
- '箇人' => array(),
937
- '網络' => array(),
938
- '网络' => array(),
939
- '组織' => array(),
940
- '網絡' => array(),
941
- '网絡' => array(),
942
- '组织' => array(),
943
- '組織' => array(),
944
- '組织' => array(),
945
- 'blogspot' => array()),
946
- 'hm' => array(),
947
- 'hn' => array('com' => array(),
948
- 'edu' => array(),
949
- 'org' => array(),
950
- 'net' => array(),
951
- 'mil' => array(),
952
- 'gob' => array()),
953
- 'hr' => array('iz' => array(),
954
- 'from' => array(),
955
- 'name' => array(),
956
- 'com' => array()),
957
- 'ht' => array('com' => array(),
958
- 'shop' => array(),
959
- 'firm' => array(),
960
- 'info' => array(),
961
- 'adult' => array(),
962
- 'net' => array(),
963
- 'pro' => array(),
964
- 'org' => array(),
965
- 'med' => array(),
966
- 'art' => array(),
967
- 'coop' => array(),
968
- 'pol' => array(),
969
- 'asso' => array(),
970
- 'edu' => array(),
971
- 'rel' => array(),
972
- 'gouv' => array(),
973
- 'perso' => array()),
974
- 'hu' => array('co' => array(),
975
- 'info' => array(),
976
- 'org' => array(),
977
- 'priv' => array(),
978
- 'sport' => array(),
979
- 'tm' => array(),
980
- '2000' => array(),
981
- 'agrar' => array(),
982
- 'bolt' => array(),
983
- 'casino' => array(),
984
- 'city' => array(),
985
- 'erotica' => array(),
986
- 'erotika' => array(),
987
- 'film' => array(),
988
- 'forum' => array(),
989
- 'games' => array(),
990
- 'hotel' => array(),
991
- 'ingatlan' => array(),
992
- 'jogasz' => array(),
993
- 'konyvelo' => array(),
994
- 'lakas' => array(),
995
- 'media' => array(),
996
- 'news' => array(),
997
- 'reklam' => array(),
998
- 'sex' => array(),
999
- 'shop' => array(),
1000
- 'suli' => array(),
1001
- 'szex' => array(),
1002
- 'tozsde' => array(),
1003
- 'utazas' => array(),
1004
- 'video' => array(),
1005
- 'blogspot' => array()),
1006
- 'id' => array('ac' => array(),
1007
- 'biz' => array(),
1008
- 'co' => array(),
1009
- 'desa' => array(),
1010
- 'go' => array(),
1011
- 'mil' => array(),
1012
- 'my' => array(),
1013
- 'net' => array(),
1014
- 'or' => array(),
1015
- 'sch' => array(),
1016
- 'web' => array()),
1017
- 'ie' => array('gov' => array(),
1018
- 'blogspot' => array()),
1019
- 'il' => array('*' => array(),
1020
- 'co' => array('blogspot' => array())),
1021
- 'im' => array('ac' => array(),
1022
- 'co' => array('ltd' => array(),
1023
- 'plc' => array()),
1024
- 'com' => array(),
1025
- 'net' => array(),
1026
- 'org' => array(),
1027
- 'tt' => array(),
1028
- 'tv' => array()),
1029
- 'in' => array('co' => array(),
1030
- 'firm' => array(),
1031
- 'net' => array(),
1032
- 'org' => array(),
1033
- 'gen' => array(),
1034
- 'ind' => array(),
1035
- 'nic' => array(),
1036
- 'ac' => array(),
1037
- 'edu' => array(),
1038
- 'res' => array(),
1039
- 'gov' => array(),
1040
- 'mil' => array(),
1041
- 'blogspot' => array()),
1042
- 'info' => array('dyndns' => array(),
1043
- 'barrel-of-knowledge' => array(),
1044
- 'barrell-of-knowledge' => array(),
1045
- 'for-our' => array(),
1046
- 'groks-the' => array(),
1047
- 'groks-this' => array(),
1048
- 'here-for-more' => array(),
1049
- 'knowsitall' => array(),
1050
- 'selfip' => array(),
1051
- 'webhop' => array()),
1052
- 'int' => array('eu' => array()),
1053
- 'io' => array('com' => array(),
1054
- 'github' => array(),
1055
- 'nid' => array()),
1056
- 'iq' => array('gov' => array(),
1057
- 'edu' => array(),
1058
- 'mil' => array(),
1059
- 'com' => array(),
1060
- 'org' => array(),
1061
- 'net' => array()),
1062
- 'ir' => array('ac' => array(),
1063
- 'co' => array(),
1064
- 'gov' => array(),
1065
- 'id' => array(),
1066
- 'net' => array(),
1067
- 'org' => array(),
1068
- 'sch' => array(),
1069
- 'ایران' => array(),
1070
- 'ايران' => array()),
1071
- 'is' => array('net' => array(),
1072
- 'com' => array(),
1073
- 'edu' => array(),
1074
- 'gov' => array(),
1075
- 'org' => array(),
1076
- 'int' => array(),
1077
- 'cupcake' => array()),
1078
- 'it' => array('gov' => array(),
1079
- 'edu' => array(),
1080
- 'abr' => array(),
1081
- 'abruzzo' => array(),
1082
- 'aosta-valley' => array(),
1083
- 'aostavalley' => array(),
1084
- 'bas' => array(),
1085
- 'basilicata' => array(),
1086
- 'cal' => array(),
1087
- 'calabria' => array(),
1088
- 'cam' => array(),
1089
- 'campania' => array(),
1090
- 'emilia-romagna' => array(),
1091
- 'emiliaromagna' => array(),
1092
- 'emr' => array(),
1093
- 'friuli-v-giulia' => array(),
1094
- 'friuli-ve-giulia' => array(),
1095
- 'friuli-vegiulia' => array(),
1096
- 'friuli-venezia-giulia' => array(),
1097
- 'friuli-veneziagiulia' => array(),
1098
- 'friuli-vgiulia' => array(),
1099
- 'friuliv-giulia' => array(),
1100
- 'friulive-giulia' => array(),
1101
- 'friulivegiulia' => array(),
1102
- 'friulivenezia-giulia' => array(),
1103
- 'friuliveneziagiulia' => array(),
1104
- 'friulivgiulia' => array(),
1105
- 'fvg' => array(),
1106
- 'laz' => array(),
1107
- 'lazio' => array(),
1108
- 'lig' => array(),
1109
- 'liguria' => array(),
1110
- 'lom' => array(),
1111
- 'lombardia' => array(),
1112
- 'lombardy' => array(),
1113
- 'lucania' => array(),
1114
- 'mar' => array(),
1115
- 'marche' => array(),
1116
- 'mol' => array(),
1117
- 'molise' => array(),
1118
- 'piedmont' => array(),
1119
- 'piemonte' => array(),
1120
- 'pmn' => array(),
1121
- 'pug' => array(),
1122
- 'puglia' => array(),
1123
- 'sar' => array(),
1124
- 'sardegna' => array(),
1125
- 'sardinia' => array(),
1126
- 'sic' => array(),
1127
- 'sicilia' => array(),
1128
- 'sicily' => array(),
1129
- 'taa' => array(),
1130
- 'tos' => array(),
1131
- 'toscana' => array(),
1132
- 'trentino-a-adige' => array(),
1133
- 'trentino-aadige' => array(),
1134
- 'trentino-alto-adige' => array(),
1135
- 'trentino-altoadige' => array(),
1136
- 'trentino-s-tirol' => array(),
1137
- 'trentino-stirol' => array(),
1138
- 'trentino-sud-tirol' => array(),
1139
- 'trentino-sudtirol' => array(),
1140
- 'trentino-sued-tirol' => array(),
1141
- 'trentino-suedtirol' => array(),
1142
- 'trentinoa-adige' => array(),
1143
- 'trentinoaadige' => array(),
1144
- 'trentinoalto-adige' => array(),
1145
- 'trentinoaltoadige' => array(),
1146
- 'trentinos-tirol' => array(),
1147
- 'trentinostirol' => array(),
1148
- 'trentinosud-tirol' => array(),
1149
- 'trentinosudtirol' => array(),
1150
- 'trentinosued-tirol' => array(),
1151
- 'trentinosuedtirol' => array(),
1152
- 'tuscany' => array(),
1153
- 'umb' => array(),
1154
- 'umbria' => array(),
1155
- 'val-d-aosta' => array(),
1156
- 'val-daosta' => array(),
1157
- 'vald-aosta' => array(),
1158
- 'valdaosta' => array(),
1159
- 'valle-aosta' => array(),
1160
- 'valle-d-aosta' => array(),
1161
- 'valle-daosta' => array(),
1162
- 'valleaosta' => array(),
1163
- 'valled-aosta' => array(),
1164
- 'valledaosta' => array(),
1165
- 'vallee-aoste' => array(),
1166
- 'valleeaoste' => array(),
1167
- 'vao' => array(),
1168
- 'vda' => array(),
1169
- 'ven' => array(),
1170
- 'veneto' => array(),
1171
- 'ag' => array(),
1172
- 'agrigento' => array(),
1173
- 'al' => array(),
1174
- 'alessandria' => array(),
1175
- 'alto-adige' => array(),
1176
- 'altoadige' => array(),
1177
- 'an' => array(),
1178
- 'ancona' => array(),
1179
- 'andria-barletta-trani' => array(),
1180
- 'andria-trani-barletta' => array(),
1181
- 'andriabarlettatrani' => array(),
1182
- 'andriatranibarletta' => array(),
1183
- 'ao' => array(),
1184
- 'aosta' => array(),
1185
- 'aoste' => array(),
1186
- 'ap' => array(),
1187
- 'aq' => array(),
1188
- 'aquila' => array(),
1189
- 'ar' => array(),
1190
- 'arezzo' => array(),
1191
- 'ascoli-piceno' => array(),
1192
- 'ascolipiceno' => array(),
1193
- 'asti' => array(),
1194
- 'at' => array(),
1195
- 'av' => array(),
1196
- 'avellino' => array(),
1197
- 'ba' => array(),
1198
- 'balsan' => array(),
1199
- 'bari' => array(),
1200
- 'barletta-trani-andria' => array(),
1201
- 'barlettatraniandria' => array(),
1202
- 'belluno' => array(),
1203
- 'benevento' => array(),
1204
- 'bergamo' => array(),
1205
- 'bg' => array(),
1206
- 'bi' => array(),
1207
- 'biella' => array(),
1208
- 'bl' => array(),
1209
- 'bn' => array(),
1210
- 'bo' => array(),
1211
- 'bologna' => array(),
1212
- 'bolzano' => array(),
1213
- 'bozen' => array(),
1214
- 'br' => array(),
1215
- 'brescia' => array(),
1216
- 'brindisi' => array(),
1217
- 'bs' => array(),
1218
- 'bt' => array(),
1219
- 'bz' => array(),
1220
- 'ca' => array(),
1221
- 'cagliari' => array(),
1222
- 'caltanissetta' => array(),
1223
- 'campidano-medio' => array(),
1224
- 'campidanomedio' => array(),
1225
- 'campobasso' => array(),
1226
- 'carbonia-iglesias' => array(),
1227
- 'carboniaiglesias' => array(),
1228
- 'carrara-massa' => array(),
1229
- 'carraramassa' => array(),
1230
- 'caserta' => array(),
1231
- 'catania' => array(),
1232
- 'catanzaro' => array(),
1233
- 'cb' => array(),
1234
- 'ce' => array(),
1235
- 'cesena-forli' => array(),
1236
- 'cesenaforli' => array(),
1237
- 'ch' => array(),
1238
- 'chieti' => array(),
1239
- 'ci' => array(),
1240
- 'cl' => array(),
1241
- 'cn' => array(),
1242
- 'co' => array(),
1243
- 'como' => array(),
1244
- 'cosenza' => array(),
1245
- 'cr' => array(),
1246
- 'cremona' => array(),
1247
- 'crotone' => array(),
1248
- 'cs' => array(),
1249
- 'ct' => array(),
1250
- 'cuneo' => array(),
1251
- 'cz' => array(),
1252
- 'dell-ogliastra' => array(),
1253
- 'dellogliastra' => array(),
1254
- 'en' => array(),
1255
- 'enna' => array(),
1256
- 'fc' => array(),
1257
- 'fe' => array(),
1258
- 'fermo' => array(),
1259
- 'ferrara' => array(),
1260
- 'fg' => array(),
1261
- 'fi' => array(),
1262
- 'firenze' => array(),
1263
- 'florence' => array(),
1264
- 'fm' => array(),
1265
- 'foggia' => array(),
1266
- 'forli-cesena' => array(),
1267
- 'forlicesena' => array(),
1268
- 'fr' => array(),
1269
- 'frosinone' => array(),
1270
- 'ge' => array(),
1271
- 'genoa' => array(),
1272
- 'genova' => array(),
1273
- 'go' => array(),
1274
- 'gorizia' => array(),
1275
- 'gr' => array(),
1276
- 'grosseto' => array(),
1277
- 'iglesias-carbonia' => array(),
1278
- 'iglesiascarbonia' => array(),
1279
- 'im' => array(),
1280
- 'imperia' => array(),
1281
- 'is' => array(),
1282
- 'isernia' => array(),
1283
- 'kr' => array(),
1284
- 'la-spezia' => array(),
1285
- 'laquila' => array(),
1286
- 'laspezia' => array(),
1287
- 'latina' => array(),
1288
- 'lc' => array(),
1289
- 'le' => array(),
1290
- 'lecce' => array(),
1291
- 'lecco' => array(),
1292
- 'li' => array(),
1293
- 'livorno' => array(),
1294
- 'lo' => array(),
1295
- 'lodi' => array(),
1296
- 'lt' => array(),
1297
- 'lu' => array(),
1298
- 'lucca' => array(),
1299
- 'macerata' => array(),
1300
- 'mantova' => array(),
1301
- 'massa-carrara' => array(),
1302
- 'massacarrara' => array(),
1303
- 'matera' => array(),
1304
- 'mb' => array(),
1305
- 'mc' => array(),
1306
- 'me' => array(),
1307
- 'medio-campidano' => array(),
1308
- 'mediocampidano' => array(),
1309
- 'messina' => array(),
1310
- 'mi' => array(),
1311
- 'milan' => array(),
1312
- 'milano' => array(),
1313
- 'mn' => array(),
1314
- 'mo' => array(),
1315
- 'modena' => array(),
1316
- 'monza-brianza' => array(),
1317
- 'monza-e-della-brianza' => array(),
1318
- 'monza' => array(),
1319
- 'monzabrianza' => array(),
1320
- 'monzaebrianza' => array(),
1321
- 'monzaedellabrianza' => array(),
1322
- 'ms' => array(),
1323
- 'mt' => array(),
1324
- 'na' => array(),
1325
- 'naples' => array(),
1326
- 'napoli' => array(),
1327
- 'no' => array(),
1328
- 'novara' => array(),
1329
- 'nu' => array(),
1330
- 'nuoro' => array(),
1331
- 'og' => array(),
1332
- 'ogliastra' => array(),
1333
- 'olbia-tempio' => array(),
1334
- 'olbiatempio' => array(),
1335
- 'or' => array(),
1336
- 'oristano' => array(),
1337
- 'ot' => array(),
1338
- 'pa' => array(),
1339
- 'padova' => array(),
1340
- 'padua' => array(),
1341
- 'palermo' => array(),
1342
- 'parma' => array(),
1343
- 'pavia' => array(),
1344
- 'pc' => array(),
1345
- 'pd' => array(),
1346
- 'pe' => array(),
1347
- 'perugia' => array(),
1348
- 'pesaro-urbino' => array(),
1349
- 'pesarourbino' => array(),
1350
- 'pescara' => array(),
1351
- 'pg' => array(),
1352
- 'pi' => array(),
1353
- 'piacenza' => array(),
1354
- 'pisa' => array(),
1355
- 'pistoia' => array(),
1356
- 'pn' => array(),
1357
- 'po' => array(),
1358
- 'pordenone' => array(),
1359
- 'potenza' => array(),
1360
- 'pr' => array(),
1361
- 'prato' => array(),
1362
- 'pt' => array(),
1363
- 'pu' => array(),
1364
- 'pv' => array(),
1365
- 'pz' => array(),
1366
- 'ra' => array(),
1367
- 'ragusa' => array(),
1368
- 'ravenna' => array(),
1369
- 'rc' => array(),
1370
- 're' => array(),
1371
- 'reggio-calabria' => array(),
1372
- 'reggio-emilia' => array(),
1373
- 'reggiocalabria' => array(),
1374
- 'reggioemilia' => array(),
1375
- 'rg' => array(),
1376
- 'ri' => array(),
1377
- 'rieti' => array(),
1378
- 'rimini' => array(),
1379
- 'rm' => array(),
1380
- 'rn' => array(),
1381
- 'ro' => array(),
1382
- 'roma' => array(),
1383
- 'rome' => array(),
1384
- 'rovigo' => array(),
1385
- 'sa' => array(),
1386
- 'salerno' => array(),
1387
- 'sassari' => array(),
1388
- 'savona' => array(),
1389
- 'si' => array(),
1390
- 'siena' => array(),
1391
- 'siracusa' => array(),
1392
- 'so' => array(),
1393
- 'sondrio' => array(),
1394
- 'sp' => array(),
1395
- 'sr' => array(),
1396
- 'ss' => array(),
1397
- 'suedtirol' => array(),
1398
- 'sv' => array(),
1399
- 'ta' => array(),
1400
- 'taranto' => array(),
1401
- 'te' => array(),
1402
- 'tempio-olbia' => array(),
1403
- 'tempioolbia' => array(),
1404
- 'teramo' => array(),
1405
- 'terni' => array(),
1406
- 'tn' => array(),
1407
- 'to' => array(),
1408
- 'torino' => array(),
1409
- 'tp' => array(),
1410
- 'tr' => array(),
1411
- 'trani-andria-barletta' => array(),
1412
- 'trani-barletta-andria' => array(),
1413
- 'traniandriabarletta' => array(),
1414
- 'tranibarlettaandria' => array(),
1415
- 'trapani' => array(),
1416
- 'trentino' => array(),
1417
- 'trento' => array(),
1418
- 'treviso' => array(),
1419
- 'trieste' => array(),
1420
- 'ts' => array(),
1421
- 'turin' => array(),
1422
- 'tv' => array(),
1423
- 'ud' => array(),
1424
- 'udine' => array(),
1425
- 'urbino-pesaro' => array(),
1426
- 'urbinopesaro' => array(),
1427
- 'va' => array(),
1428
- 'varese' => array(),
1429
- 'vb' => array(),
1430
- 'vc' => array(),
1431
- 've' => array(),
1432
- 'venezia' => array(),
1433
- 'venice' => array(),
1434
- 'verbania' => array(),
1435
- 'vercelli' => array(),
1436
- 'verona' => array(),
1437
- 'vi' => array(),
1438
- 'vibo-valentia' => array(),
1439
- 'vibovalentia' => array(),
1440
- 'vicenza' => array(),
1441
- 'viterbo' => array(),
1442
- 'vr' => array(),
1443
- 'vs' => array(),
1444
- 'vt' => array(),
1445
- 'vv' => array(),
1446
- 'blogspot' => array()),
1447
- 'je' => array('co' => array(),
1448
- 'net' => array(),
1449
- 'org' => array()),
1450
- 'jm' => array('*' => array()),
1451
- 'jo' => array('com' => array(),
1452
- 'org' => array(),
1453
- 'net' => array(),
1454
- 'edu' => array(),
1455
- 'sch' => array(),
1456
- 'gov' => array(),
1457
- 'mil' => array(),
1458
- 'name' => array()),
1459
- 'jobs' => array(),
1460
- 'jp' => array('ac' => array(),
1461
- 'ad' => array(),
1462
- 'co' => array(),
1463
- 'ed' => array(),
1464
- 'go' => array(),
1465
- 'gr' => array(),
1466
- 'lg' => array(),
1467
- 'ne' => array(),
1468
- 'or' => array(),
1469
- 'aichi' => array('aisai' => array(),
1470
- 'ama' => array(),
1471
- 'anjo' => array(),
1472
- 'asuke' => array(),
1473
- 'chiryu' => array(),
1474
- 'chita' => array(),
1475
- 'fuso' => array(),
1476
- 'gamagori' => array(),
1477
- 'handa' => array(),
1478
- 'hazu' => array(),
1479
- 'hekinan' => array(),
1480
- 'higashiura' => array(),
1481
- 'ichinomiya' => array(),
1482
- 'inazawa' => array(),
1483
- 'inuyama' => array(),
1484
- 'isshiki' => array(),
1485
- 'iwakura' => array(),
1486
- 'kanie' => array(),
1487
- 'kariya' => array(),
1488
- 'kasugai' => array(),
1489
- 'kira' => array(),
1490
- 'kiyosu' => array(),
1491
- 'komaki' => array(),
1492
- 'konan' => array(),
1493
- 'kota' => array(),
1494
- 'mihama' => array(),
1495
- 'miyoshi' => array(),
1496
- 'nishio' => array(),
1497
- 'nisshin' => array(),
1498
- 'obu' => array(),
1499
- 'oguchi' => array(),
1500
- 'oharu' => array(),
1501
- 'okazaki' => array(),
1502
- 'owariasahi' => array(),
1503
- 'seto' => array(),
1504
- 'shikatsu' => array(),
1505
- 'shinshiro' => array(),
1506
- 'shitara' => array(),
1507
- 'tahara' => array(),
1508
- 'takahama' => array(),
1509
- 'tobishima' => array(),
1510
- 'toei' => array(),
1511
- 'togo' => array(),
1512
- 'tokai' => array(),
1513
- 'tokoname' => array(),
1514
- 'toyoake' => array(),
1515
- 'toyohashi' => array(),
1516
- 'toyokawa' => array(),
1517
- 'toyone' => array(),
1518
- 'toyota' => array(),
1519
- 'tsushima' => array(),
1520
- 'yatomi' => array()),
1521
- 'akita' => array('akita' => array(),
1522
- 'daisen' => array(),
1523
- 'fujisato' => array(),
1524
- 'gojome' => array(),
1525
- 'hachirogata' => array(),
1526
- 'happou' => array(),
1527
- 'higashinaruse' => array(),
1528
- 'honjo' => array(),
1529
- 'honjyo' => array(),
1530
- 'ikawa' => array(),
1531
- 'kamikoani' => array(),
1532
- 'kamioka' => array(),
1533
- 'katagami' => array(),
1534
- 'kazuno' => array(),
1535
- 'kitaakita' => array(),
1536
- 'kosaka' => array(),
1537
- 'kyowa' => array(),
1538
- 'misato' => array(),
1539
- 'mitane' => array(),
1540
- 'moriyoshi' => array(),
1541
- 'nikaho' => array(),
1542
- 'noshiro' => array(),
1543
- 'odate' => array(),
1544
- 'oga' => array(),
1545
- 'ogata' => array(),
1546
- 'semboku' => array(),
1547
- 'yokote' => array(),
1548
- 'yurihonjo' => array()),
1549
- 'aomori' => array('aomori' => array(),
1550
- 'gonohe' => array(),
1551
- 'hachinohe' => array(),
1552
- 'hashikami' => array(),
1553
- 'hiranai' => array(),
1554
- 'hirosaki' => array(),
1555
- 'itayanagi' => array(),
1556
- 'kuroishi' => array(),
1557
- 'misawa' => array(),
1558
- 'mutsu' => array(),
1559
- 'nakadomari' => array(),
1560
- 'noheji' => array(),
1561
- 'oirase' => array(),
1562
- 'owani' => array(),
1563
- 'rokunohe' => array(),
1564
- 'sannohe' => array(),
1565
- 'shichinohe' => array(),
1566
- 'shingo' => array(),
1567
- 'takko' => array(),
1568
- 'towada' => array(),
1569
- 'tsugaru' => array(),
1570
- 'tsuruta' => array()),
1571
- 'chiba' => array('abiko' => array(),
1572
- 'asahi' => array(),
1573
- 'chonan' => array(),
1574
- 'chosei' => array(),
1575
- 'choshi' => array(),
1576
- 'chuo' => array(),
1577
- 'funabashi' => array(),
1578
- 'futtsu' => array(),
1579
- 'hanamigawa' => array(),
1580
- 'ichihara' => array(),
1581
- 'ichikawa' => array(),
1582
- 'ichinomiya' => array(),
1583
- 'inzai' => array(),
1584
- 'isumi' => array(),
1585
- 'kamagaya' => array(),
1586
- 'kamogawa' => array(),
1587
- 'kashiwa' => array(),
1588
- 'katori' => array(),
1589
- 'katsuura' => array(),
1590
- 'kimitsu' => array(),
1591
- 'kisarazu' => array(),
1592
- 'kozaki' => array(),
1593
- 'kujukuri' => array(),
1594
- 'kyonan' => array(),
1595
- 'matsudo' => array(),
1596
- 'midori' => array(),
1597
- 'mihama' => array(),
1598
- 'minamiboso' => array(),
1599
- 'mobara' => array(),
1600
- 'mutsuzawa' => array(),
1601
- 'nagara' => array(),
1602
- 'nagareyama' => array(),
1603
- 'narashino' => array(),
1604
- 'narita' => array(),
1605
- 'noda' => array(),
1606
- 'oamishirasato' => array(),
1607
- 'omigawa' => array(),
1608
- 'onjuku' => array(),
1609
- 'otaki' => array(),
1610
- 'sakae' => array(),
1611
- 'sakura' => array(),
1612
- 'shimofusa' => array(),
1613
- 'shirako' => array(),
1614
- 'shiroi' => array(),
1615
- 'shisui' => array(),
1616
- 'sodegaura' => array(),
1617
- 'sosa' => array(),
1618
- 'tako' => array(),
1619
- 'tateyama' => array(),
1620
- 'togane' => array(),
1621
- 'tohnosho' => array(),
1622
- 'tomisato' => array(),
1623
- 'urayasu' => array(),
1624
- 'yachimata' => array(),
1625
- 'yachiyo' => array(),
1626
- 'yokaichiba' => array(),
1627
- 'yokoshibahikari' => array(),
1628
- 'yotsukaido' => array()),
1629
- 'ehime' => array('ainan' => array(),
1630
- 'honai' => array(),
1631
- 'ikata' => array(),
1632
- 'imabari' => array(),
1633
- 'iyo' => array(),
1634
- 'kamijima' => array(),
1635
- 'kihoku' => array(),
1636
- 'kumakogen' => array(),
1637
- 'masaki' => array(),
1638
- 'matsuno' => array(),
1639
- 'matsuyama' => array(),
1640
- 'namikata' => array(),
1641
- 'niihama' => array(),
1642
- 'ozu' => array(),
1643
- 'saijo' => array(),
1644
- 'seiyo' => array(),
1645
- 'shikokuchuo' => array(),
1646
- 'tobe' => array(),
1647
- 'toon' => array(),
1648
- 'uchiko' => array(),
1649
- 'uwajima' => array(),
1650
- 'yawatahama' => array()),
1651
- 'fukui' => array('echizen' => array(),
1652
- 'eiheiji' => array(),
1653
- 'fukui' => array(),
1654
- 'ikeda' => array(),
1655
- 'katsuyama' => array(),
1656
- 'mihama' => array(),
1657
- 'minamiechizen' => array(),
1658
- 'obama' => array(),
1659
- 'ohi' => array(),
1660
- 'ono' => array(),
1661
- 'sabae' => array(),
1662
- 'sakai' => array(),
1663
- 'takahama' => array(),
1664
- 'tsuruga' => array(),
1665
- 'wakasa' => array()),
1666
- 'fukuoka' => array('ashiya' => array(),
1667
- 'buzen' => array(),
1668
- 'chikugo' => array(),
1669
- 'chikuho' => array(),
1670
- 'chikujo' => array(),
1671
- 'chikushino' => array(),
1672
- 'chikuzen' => array(),
1673
- 'chuo' => array(),
1674
- 'dazaifu' => array(),
1675
- 'fukuchi' => array(),
1676
- 'hakata' => array(),
1677
- 'higashi' => array(),
1678
- 'hirokawa' => array(),
1679
- 'hisayama' => array(),
1680
- 'iizuka' => array(),
1681
- 'inatsuki' => array(),
1682
- 'kaho' => array(),
1683
- 'kasuga' => array(),
1684
- 'kasuya' => array(),
1685
- 'kawara' => array(),
1686
- 'keisen' => array(),
1687
- 'koga' => array(),
1688
- 'kurate' => array(),
1689
- 'kurogi' => array(),
1690
- 'kurume' => array(),
1691
- 'minami' => array(),
1692
- 'miyako' => array(),
1693
- 'miyama' => array(),
1694
- 'miyawaka' => array(),
1695
- 'mizumaki' => array(),
1696
- 'munakata' => array(),
1697
- 'nakagawa' => array(),
1698
- 'nakama' => array(),
1699
- 'nishi' => array(),
1700
- 'nogata' => array(),
1701
- 'ogori' => array(),
1702
- 'okagaki' => array(),
1703
- 'okawa' => array(),
1704
- 'oki' => array(),
1705
- 'omuta' => array(),
1706
- 'onga' => array(),
1707
- 'onojo' => array(),
1708
- 'oto' => array(),
1709
- 'saigawa' => array(),
1710
- 'sasaguri' => array(),
1711
- 'shingu' => array(),
1712
- 'shinyoshitomi' => array(),
1713
- 'shonai' => array(),
1714
- 'soeda' => array(),
1715
- 'sue' => array(),
1716
- 'tachiarai' => array(),
1717
- 'tagawa' => array(),
1718
- 'takata' => array(),
1719
- 'toho' => array(),
1720
- 'toyotsu' => array(),
1721
- 'tsuiki' => array(),
1722
- 'ukiha' => array(),
1723
- 'umi' => array(),
1724
- 'usui' => array(),
1725
- 'yamada' => array(),
1726
- 'yame' => array(),
1727
- 'yanagawa' => array(),
1728
- 'yukuhashi' => array()),
1729
- 'fukushima' => array('aizubange' => array(),
1730
- 'aizumisato' => array(),
1731
- 'aizuwakamatsu' => array(),
1732
- 'asakawa' => array(),
1733
- 'bandai' => array(),
1734
- 'date' => array(),
1735
- 'fukushima' => array(),
1736
- 'furudono' => array(),
1737
- 'futaba' => array(),
1738
- 'hanawa' => array(),
1739
- 'higashi' => array(),
1740
- 'hirata' => array(),
1741
- 'hirono' => array(),
1742
- 'iitate' => array(),
1743
- 'inawashiro' => array(),
1744
- 'ishikawa' => array(),
1745
- 'iwaki' => array(),
1746
- 'izumizaki' => array(),
1747
- 'kagamiishi' => array(),
1748
- 'kaneyama' => array(),
1749
- 'kawamata' => array(),
1750
- 'kitakata' => array(),
1751
- 'kitashiobara' => array(),
1752
- 'koori' => array(),
1753
- 'koriyama' => array(),
1754
- 'kunimi' => array(),
1755
- 'miharu' => array(),
1756
- 'mishima' => array(),
1757
- 'namie' => array(),
1758
- 'nango' => array(),
1759
- 'nishiaizu' => array(),
1760
- 'nishigo' => array(),
1761
- 'okuma' => array(),
1762
- 'omotego' => array(),
1763
- 'ono' => array(),
1764
- 'otama' => array(),
1765
- 'samegawa' => array(),
1766
- 'shimogo' => array(),
1767
- 'shirakawa' => array(),
1768
- 'showa' => array(),
1769
- 'soma' => array(),
1770
- 'sukagawa' => array(),
1771
- 'taishin' => array(),
1772
- 'tamakawa' => array(),
1773
- 'tanagura' => array(),
1774
- 'tenei' => array(),
1775
- 'yabuki' => array(),
1776
- 'yamato' => array(),
1777
- 'yamatsuri' => array(),
1778
- 'yanaizu' => array(),
1779
- 'yugawa' => array()),
1780
- 'gifu' => array('anpachi' => array(),
1781
- 'ena' => array(),
1782
- 'gifu' => array(),
1783
- 'ginan' => array(),
1784
- 'godo' => array(),
1785
- 'gujo' => array(),
1786
- 'hashima' => array(),
1787
- 'hichiso' => array(),
1788
- 'hida' => array(),
1789
- 'higashishirakawa' => array(),
1790
- 'ibigawa' => array(),
1791
- 'ikeda' => array(),
1792
- 'kakamigahara' => array(),
1793
- 'kani' => array(),
1794
- 'kasahara' => array(),
1795
- 'kasamatsu' => array(),
1796
- 'kawaue' => array(),
1797
- 'kitagata' => array(),
1798
- 'mino' => array(),
1799
- 'minokamo' => array(),
1800
- 'mitake' => array(),
1801
- 'mizunami' => array(),
1802
- 'motosu' => array(),
1803
- 'nakatsugawa' => array(),
1804
- 'ogaki' => array(),
1805
- 'sakahogi' => array(),
1806
- 'seki' => array(),
1807
- 'sekigahara' => array(),
1808
- 'shirakawa' => array(),
1809
- 'tajimi' => array(),
1810
- 'takayama' => array(),
1811
- 'tarui' => array(),
1812
- 'toki' => array(),
1813
- 'tomika' => array(),
1814
- 'wanouchi' => array(),
1815
- 'yamagata' => array(),
1816
- 'yaotsu' => array(),
1817
- 'yoro' => array()),
1818
- 'gunma' => array('annaka' => array(),
1819
- 'chiyoda' => array(),
1820
- 'fujioka' => array(),
1821
- 'higashiagatsuma' => array(),
1822
- 'isesaki' => array(),
1823
- 'itakura' => array(),
1824
- 'kanna' => array(),
1825
- 'kanra' => array(),
1826
- 'katashina' => array(),
1827
- 'kawaba' => array(),
1828
- 'kiryu' => array(),
1829
- 'kusatsu' => array(),
1830
- 'maebashi' => array(),
1831
- 'meiwa' => array(),
1832
- 'midori' => array(),
1833
- 'minakami' => array(),
1834
- 'naganohara' => array(),
1835
- 'nakanojo' => array(),
1836
- 'nanmoku' => array(),
1837
- 'numata' => array(),
1838
- 'oizumi' => array(),
1839
- 'ora' => array(),
1840
- 'ota' => array(),
1841
- 'shibukawa' => array(),
1842
- 'shimonita' => array(),
1843
- 'shinto' => array(),
1844
- 'showa' => array(),
1845
- 'takasaki' => array(),
1846
- 'takayama' => array(),
1847
- 'tamamura' => array(),
1848
- 'tatebayashi' => array(),
1849
- 'tomioka' => array(),
1850
- 'tsukiyono' => array(),
1851
- 'tsumagoi' => array(),
1852
- 'ueno' => array(),
1853
- 'yoshioka' => array()),
1854
- 'hiroshima' => array('asaminami' => array(),
1855
- 'daiwa' => array(),
1856
- 'etajima' => array(),
1857
- 'fuchu' => array(),
1858
- 'fukuyama' => array(),
1859
- 'hatsukaichi' => array(),
1860
- 'higashihiroshima' => array(),
1861
- 'hongo' => array(),
1862
- 'jinsekikogen' => array(),
1863
- 'kaita' => array(),
1864
- 'kui' => array(),
1865
- 'kumano' => array(),
1866
- 'kure' => array(),
1867
- 'mihara' => array(),
1868
- 'miyoshi' => array(),
1869
- 'naka' => array(),
1870
- 'onomichi' => array(),
1871
- 'osakikamijima' => array(),
1872
- 'otake' => array(),
1873
- 'saka' => array(),
1874
- 'sera' => array(),
1875
- 'seranishi' => array(),
1876
- 'shinichi' => array(),
1877
- 'shobara' => array(),
1878
- 'takehara' => array()),
1879
- 'hokkaido' => array('abashiri' => array(),
1880
- 'abira' => array(),
1881
- 'aibetsu' => array(),
1882
- 'akabira' => array(),
1883
- 'akkeshi' => array(),
1884
- 'asahikawa' => array(),
1885
- 'ashibetsu' => array(),
1886
- 'ashoro' => array(),
1887
- 'assabu' => array(),
1888
- 'atsuma' => array(),
1889
- 'bibai' => array(),
1890
- 'biei' => array(),
1891
- 'bifuka' => array(),
1892
- 'bihoro' => array(),
1893
- 'biratori' => array(),
1894
- 'chippubetsu' => array(),
1895
- 'chitose' => array(),
1896
- 'date' => array(),
1897
- 'ebetsu' => array(),
1898
- 'embetsu' => array(),
1899
- 'eniwa' => array(),
1900
- 'erimo' => array(),
1901
- 'esan' => array(),
1902
- 'esashi' => array(),
1903
- 'fukagawa' => array(),
1904
- 'fukushima' => array(),
1905
- 'furano' => array(),
1906
- 'furubira' => array(),
1907
- 'haboro' => array(),
1908
- 'hakodate' => array(),
1909
- 'hamatonbetsu' => array(),
1910
- 'hidaka' => array(),
1911
- 'higashikagura' => array(),
1912
- 'higashikawa' => array(),
1913
- 'hiroo' => array(),
1914
- 'hokuryu' => array(),
1915
- 'hokuto' => array(),
1916
- 'honbetsu' => array(),
1917
- 'horokanai' => array(),
1918
- 'horonobe' => array(),
1919
- 'ikeda' => array(),
1920
- 'imakane' => array(),
1921
- 'ishikari' => array(),
1922
- 'iwamizawa' => array(),
1923
- 'iwanai' => array(),
1924
- 'kamifurano' => array(),
1925
- 'kamikawa' => array(),
1926
- 'kamishihoro' => array(),
1927
- 'kamisunagawa' => array(),
1928
- 'kamoenai' => array(),
1929
- 'kayabe' => array(),
1930
- 'kembuchi' => array(),
1931
- 'kikonai' => array(),
1932
- 'kimobetsu' => array(),
1933
- 'kitahiroshima' => array(),
1934
- 'kitami' => array(),
1935
- 'kiyosato' => array(),
1936
- 'koshimizu' => array(),
1937
- 'kunneppu' => array(),
1938
- 'kuriyama' => array(),
1939
- 'kuromatsunai' => array(),
1940
- 'kushiro' => array(),
1941
- 'kutchan' => array(),
1942
- 'kyowa' => array(),
1943
- 'mashike' => array(),
1944
- 'matsumae' => array(),
1945
- 'mikasa' => array(),
1946
- 'minamifurano' => array(),
1947
- 'mombetsu' => array(),
1948
- 'moseushi' => array(),
1949
- 'mukawa' => array(),
1950
- 'muroran' => array(),
1951
- 'naie' => array(),
1952
- 'nakagawa' => array(),
1953
- 'nakasatsunai' => array(),
1954
- 'nakatombetsu' => array(),
1955
- 'nanae' => array(),
1956
- 'nanporo' => array(),
1957
- 'nayoro' => array(),
1958
- 'nemuro' => array(),
1959
- 'niikappu' => array(),
1960
- 'niki' => array(),
1961
- 'nishiokoppe' => array(),
1962
- 'noboribetsu' => array(),
1963
- 'numata' => array(),
1964
- 'obihiro' => array(),
1965
- 'obira' => array(),
1966
- 'oketo' => array(),
1967
- 'okoppe' => array(),
1968
- 'otaru' => array(),
1969
- 'otobe' => array(),
1970
- 'otofuke' => array(),
1971
- 'otoineppu' => array(),
1972
- 'oumu' => array(),
1973
- 'ozora' => array(),
1974
- 'pippu' => array(),
1975
- 'rankoshi' => array(),
1976
- 'rebun' => array(),
1977
- 'rikubetsu' => array(),
1978
- 'rishiri' => array(),
1979
- 'rishirifuji' => array(),
1980
- 'saroma' => array(),
1981
- 'sarufutsu' => array(),
1982
- 'shakotan' => array(),
1983
- 'shari' => array(),
1984
- 'shibecha' => array(),
1985
- 'shibetsu' => array(),
1986
- 'shikabe' => array(),
1987
- 'shikaoi' => array(),
1988
- 'shimamaki' => array(),
1989
- 'shimizu' => array(),
1990
- 'shimokawa' => array(),
1991
- 'shinshinotsu' => array(),
1992
- 'shintoku' => array(),
1993
- 'shiranuka' => array(),
1994
- 'shiraoi' => array(),
1995
- 'shiriuchi' => array(),
1996
- 'sobetsu' => array(),
1997
- 'sunagawa' => array(),
1998
- 'taiki' => array(),
1999
- 'takasu' => array(),
2000
- 'takikawa' => array(),
2001
- 'takinoue' => array(),
2002
- 'teshikaga' => array(),
2003
- 'tobetsu' => array(),
2004
- 'tohma' => array(),
2005
- 'tomakomai' => array(),
2006
- 'tomari' => array(),
2007
- 'toya' => array(),
2008
- 'toyako' => array(),
2009
- 'toyotomi' => array(),
2010
- 'toyoura' => array(),
2011
- 'tsubetsu' => array(),
2012
- 'tsukigata' => array(),
2013
- 'urakawa' => array(),
2014
- 'urausu' => array(),
2015
- 'uryu' => array(),
2016
- 'utashinai' => array(),
2017
- 'wakkanai' => array(),
2018
- 'wassamu' => array(),
2019
- 'yakumo' => array(),
2020
- 'yoichi' => array()),
2021
- 'hyogo' => array('aioi' => array(),
2022
- 'akashi' => array(),
2023
- 'ako' => array(),
2024
- 'amagasaki' => array(),
2025
- 'aogaki' => array(),
2026
- 'asago' => array(),
2027
- 'ashiya' => array(),
2028
- 'awaji' => array(),
2029
- 'fukusaki' => array(),
2030
- 'goshiki' => array(),
2031
- 'harima' => array(),
2032
- 'himeji' => array(),
2033
- 'ichikawa' => array(),
2034
- 'inagawa' => array(),
2035
- 'itami' => array(),
2036
- 'kakogawa' => array(),
2037
- 'kamigori' => array(),
2038
- 'kamikawa' => array(),
2039
- 'kasai' => array(),
2040
- 'kasuga' => array(),
2041
- 'kawanishi' => array(),
2042
- 'miki' => array(),
2043
- 'minamiawaji' => array(),
2044
- 'nishinomiya' => array(),
2045
- 'nishiwaki' => array(),
2046
- 'ono' => array(),
2047
- 'sanda' => array(),
2048
- 'sannan' => array(),
2049
- 'sasayama' => array(),
2050
- 'sayo' => array(),
2051
- 'shingu' => array(),
2052
- 'shinonsen' => array(),
2053
- 'shiso' => array(),
2054
- 'sumoto' => array(),
2055
- 'taishi' => array(),
2056
- 'taka' => array(),
2057
- 'takarazuka' => array(),
2058
- 'takasago' => array(),
2059
- 'takino' => array(),
2060
- 'tamba' => array(),
2061
- 'tatsuno' => array(),
2062
- 'toyooka' => array(),
2063
- 'yabu' => array(),
2064
- 'yashiro' => array(),
2065
- 'yoka' => array(),
2066
- 'yokawa' => array()),
2067
- 'ibaraki' => array('ami' => array(),
2068
- 'asahi' => array(),
2069
- 'bando' => array(),
2070
- 'chikusei' => array(),
2071
- 'daigo' => array(),
2072
- 'fujishiro' => array(),
2073
- 'hitachi' => array(),
2074
- 'hitachinaka' => array(),
2075
- 'hitachiomiya' => array(),
2076
- 'hitachiota' => array(),
2077
- 'ibaraki' => array(),
2078
- 'ina' => array(),
2079
- 'inashiki' => array(),
2080
- 'itako' => array(),
2081
- 'iwama' => array(),
2082
- 'joso' => array(),
2083
- 'kamisu' => array(),
2084
- 'kasama' => array(),
2085
- 'kashima' => array(),
2086
- 'kasumigaura' => array(),
2087
- 'koga' => array(),
2088
- 'miho' => array(),
2089
- 'mito' => array(),
2090
- 'moriya' => array(),
2091
- 'naka' => array(),
2092
- 'namegata' => array(),
2093
- 'oarai' => array(),
2094
- 'ogawa' => array(),
2095
- 'omitama' => array(),
2096
- 'ryugasaki' => array(),
2097
- 'sakai' => array(),
2098
- 'sakuragawa' => array(),
2099
- 'shimodate' => array(),
2100
- 'shimotsuma' => array(),
2101
- 'shirosato' => array(),
2102
- 'sowa' => array(),
2103
- 'suifu' => array(),
2104
- 'takahagi' => array(),
2105
- 'tamatsukuri' => array(),
2106
- 'tokai' => array(),
2107
- 'tomobe' => array(),
2108
- 'tone' => array(),
2109
- 'toride' => array(),
2110
- 'tsuchiura' => array(),
2111
- 'tsukuba' => array(),
2112
- 'uchihara' => array(),
2113
- 'ushiku' => array(),
2114
- 'yachiyo' => array(),
2115
- 'yamagata' => array(),
2116
- 'yawara' => array(),
2117
- 'yuki' => array()),
2118
- 'ishikawa' => array('anamizu' => array(),
2119
- 'hakui' => array(),
2120
- 'hakusan' => array(),
2121
- 'kaga' => array(),
2122
- 'kahoku' => array(),
2123
- 'kanazawa' => array(),
2124
- 'kawakita' => array(),
2125
- 'komatsu' => array(),
2126
- 'nakanoto' => array(),
2127
- 'nanao' => array(),
2128
- 'nomi' => array(),
2129
- 'nonoichi' => array(),
2130
- 'noto' => array(),
2131
- 'shika' => array(),
2132
- 'suzu' => array(),
2133
- 'tsubata' => array(),
2134
- 'tsurugi' => array(),
2135
- 'uchinada' => array(),
2136
- 'wajima' => array()),
2137
- 'iwate' => array('fudai' => array(),
2138
- 'fujisawa' => array(),
2139
- 'hanamaki' => array(),
2140
- 'hiraizumi' => array(),
2141
- 'hirono' => array(),
2142
- 'ichinohe' => array(),
2143
- 'ichinoseki' => array(),
2144
- 'iwaizumi' => array(),
2145
- 'iwate' => array(),
2146
- 'joboji' => array(),
2147
- 'kamaishi' => array(),
2148
- 'kanegasaki' => array(),
2149
- 'karumai' => array(),
2150
- 'kawai' => array(),
2151
- 'kitakami' => array(),
2152
- 'kuji' => array(),
2153
- 'kunohe' => array(),
2154
- 'kuzumaki' => array(),
2155
- 'miyako' => array(),
2156
- 'mizusawa' => array(),
2157
- 'morioka' => array(),
2158
- 'ninohe' => array(),
2159
- 'noda' => array(),
2160
- 'ofunato' => array(),
2161
- 'oshu' => array(),
2162
- 'otsuchi' => array(),
2163
- 'rikuzentakata' => array(),
2164
- 'shiwa' => array(),
2165
- 'shizukuishi' => array(),
2166
- 'sumita' => array(),
2167
- 'tanohata' => array(),
2168
- 'tono' => array(),
2169
- 'yahaba' => array(),
2170
- 'yamada' => array()),
2171
- 'kagawa' => array('ayagawa' => array(),
2172
- 'higashikagawa' => array(),
2173
- 'kanonji' => array(),
2174
- 'kotohira' => array(),
2175
- 'manno' => array(),
2176
- 'marugame' => array(),
2177
- 'mitoyo' => array(),
2178
- 'naoshima' => array(),
2179
- 'sanuki' => array(),
2180
- 'tadotsu' => array(),
2181
- 'takamatsu' => array(),
2182
- 'tonosho' => array(),
2183
- 'uchinomi' => array(),
2184
- 'utazu' => array(),
2185
- 'zentsuji' => array()),
2186
- 'kagoshima' => array('akune' => array(),
2187
- 'amami' => array(),
2188
- 'hioki' => array(),
2189
- 'isa' => array(),
2190
- 'isen' => array(),
2191
- 'izumi' => array(),
2192
- 'kagoshima' => array(),
2193
- 'kanoya' => array(),
2194
- 'kawanabe' => array(),
2195
- 'kinko' => array(),
2196
- 'kouyama' => array(),
2197
- 'makurazaki' => array(),
2198
- 'matsumoto' => array(),
2199
- 'minamitane' => array(),
2200
- 'nakatane' => array(),
2201
- 'nishinoomote' => array(),
2202
- 'satsumasendai' => array(),
2203
- 'soo' => array(),
2204
- 'tarumizu' => array(),
2205
- 'yusui' => array()),
2206
- 'kanagawa' => array('aikawa' => array(),
2207
- 'atsugi' => array(),
2208
- 'ayase' => array(),
2209
- 'chigasaki' => array(),
2210
- 'ebina' => array(),
2211
- 'fujisawa' => array(),
2212
- 'hadano' => array(),
2213
- 'hakone' => array(),
2214
- 'hiratsuka' => array(),
2215
- 'isehara' => array(),
2216
- 'kaisei' => array(),
2217
- 'kamakura' => array(),
2218
- 'kiyokawa' => array(),
2219
- 'matsuda' => array(),
2220
- 'minamiashigara' => array(),
2221
- 'miura' => array(),
2222
- 'nakai' => array(),
2223
- 'ninomiya' => array(),
2224
- 'odawara' => array(),
2225
- 'oi' => array(),
2226
- 'oiso' => array(),
2227
- 'sagamihara' => array(),
2228
- 'samukawa' => array(),
2229
- 'tsukui' => array(),
2230
- 'yamakita' => array(),
2231
- 'yamato' => array(),
2232
- 'yokosuka' => array(),
2233
- 'yugawara' => array(),
2234
- 'zama' => array(),
2235
- 'zushi' => array()),
2236
- 'kochi' => array('aki' => array(),
2237
- 'geisei' => array(),
2238
- 'hidaka' => array(),
2239
- 'higashitsuno' => array(),
2240
- 'ino' => array(),
2241
- 'kagami' => array(),
2242
- 'kami' => array(),
2243
- 'kitagawa' => array(),
2244
- 'kochi' => array(),
2245
- 'mihara' => array(),
2246
- 'motoyama' => array(),
2247
- 'muroto' => array(),
2248
- 'nahari' => array(),
2249
- 'nakamura' => array(),
2250
- 'nankoku' => array(),
2251
- 'nishitosa' => array(),
2252
- 'niyodogawa' => array(),
2253
- 'ochi' => array(),
2254
- 'okawa' => array(),
2255
- 'otoyo' => array(),
2256
- 'otsuki' => array(),
2257
- 'sakawa' => array(),
2258
- 'sukumo' => array(),
2259
- 'susaki' => array(),
2260
- 'tosa' => array(),
2261
- 'tosashimizu' => array(),
2262
- 'toyo' => array(),
2263
- 'tsuno' => array(),
2264
- 'umaji' => array(),
2265
- 'yasuda' => array(),
2266
- 'yusuhara' => array()),
2267
- 'kumamoto' => array('amakusa' => array(),
2268
- 'arao' => array(),
2269
- 'aso' => array(),
2270
- 'choyo' => array(),
2271
- 'gyokuto' => array(),
2272
- 'hitoyoshi' => array(),
2273
- 'kamiamakusa' => array(),
2274
- 'kashima' => array(),
2275
- 'kikuchi' => array(),
2276
- 'kosa' => array(),
2277
- 'kumamoto' => array(),
2278
- 'mashiki' => array(),
2279
- 'mifune' => array(),
2280
- 'minamata' => array(),
2281
- 'minamioguni' => array(),
2282
- 'nagasu' => array(),
2283
- 'nishihara' => array(),
2284
- 'oguni' => array(),
2285
- 'ozu' => array(),
2286
- 'sumoto' => array(),
2287
- 'takamori' => array(),
2288
- 'uki' => array(),
2289
- 'uto' => array(),
2290
- 'yamaga' => array(),
2291
- 'yamato' => array(),
2292
- 'yatsushiro' => array()),
2293
- 'kyoto' => array('ayabe' => array(),
2294
- 'fukuchiyama' => array(),
2295
- 'higashiyama' => array(),
2296
- 'ide' => array(),
2297
- 'ine' => array(),
2298
- 'joyo' => array(),
2299
- 'kameoka' => array(),
2300
- 'kamo' => array(),
2301
- 'kita' => array(),
2302
- 'kizu' => array(),
2303
- 'kumiyama' => array(),
2304
- 'kyotamba' => array(),
2305
- 'kyotanabe' => array(),
2306
- 'kyotango' => array(),
2307
- 'maizuru' => array(),
2308
- 'minami' => array(),
2309
- 'minamiyamashiro' => array(),
2310
- 'miyazu' => array(),
2311
- 'muko' => array(),
2312
- 'nagaokakyo' => array(),
2313
- 'nakagyo' => array(),
2314
- 'nantan' => array(),
2315
- 'oyamazaki' => array(),
2316
- 'sakyo' => array(),
2317
- 'seika' => array(),
2318
- 'tanabe' => array(),
2319
- 'uji' => array(),
2320
- 'ujitawara' => array(),
2321
- 'wazuka' => array(),
2322
- 'yamashina' => array(),
2323
- 'yawata' => array()),
2324
- 'mie' => array('asahi' => array(),
2325
- 'inabe' => array(),
2326
- 'ise' => array(),
2327
- 'kameyama' => array(),
2328
- 'kawagoe' => array(),
2329
- 'kiho' => array(),
2330
- 'kisosaki' => array(),
2331
- 'kiwa' => array(),
2332
- 'komono' => array(),
2333
- 'kumano' => array(),
2334
- 'kuwana' => array(),
2335
- 'matsusaka' => array(),
2336
- 'meiwa' => array(),
2337
- 'mihama' => array(),
2338
- 'minamiise' => array(),
2339
- 'misugi' => array(),
2340
- 'miyama' => array(),
2341
- 'nabari' => array(),
2342
- 'shima' => array(),
2343
- 'suzuka' => array(),
2344
- 'tado' => array(),
2345
- 'taiki' => array(),
2346
- 'taki' => array(),
2347
- 'tamaki' => array(),
2348
- 'toba' => array(),
2349
- 'tsu' => array(),
2350
- 'udono' => array(),
2351
- 'ureshino' => array(),
2352
- 'watarai' => array(),
2353
- 'yokkaichi' => array()),
2354
- 'miyagi' => array('furukawa' => array(),
2355
- 'higashimatsushima' => array(),
2356
- 'ishinomaki' => array(),
2357
- 'iwanuma' => array(),
2358
- 'kakuda' => array(),
2359
- 'kami' => array(),
2360
- 'kawasaki' => array(),
2361
- 'kesennuma' => array(),
2362
- 'marumori' => array(),
2363
- 'matsushima' => array(),
2364
- 'minamisanriku' => array(),
2365
- 'misato' => array(),
2366
- 'murata' => array(),
2367
- 'natori' => array(),
2368
- 'ogawara' => array(),
2369
- 'ohira' => array(),
2370
- 'onagawa' => array(),
2371
- 'osaki' => array(),
2372
- 'rifu' => array(),
2373
- 'semine' => array(),
2374
- 'shibata' => array(),
2375
- 'shichikashuku' => array(),
2376
- 'shikama' => array(),
2377
- 'shiogama' => array(),
2378
- 'shiroishi' => array(),
2379
- 'tagajo' => array(),
2380
- 'taiwa' => array(),
2381
- 'tome' => array(),
2382
- 'tomiya' => array(),
2383
- 'wakuya' => array(),
2384
- 'watari' => array(),
2385
- 'yamamoto' => array(),
2386
- 'zao' => array()),
2387
- 'miyazaki' => array('aya' => array(),
2388
- 'ebino' => array(),
2389
- 'gokase' => array(),
2390
- 'hyuga' => array(),
2391
- 'kadogawa' => array(),
2392
- 'kawaminami' => array(),
2393
- 'kijo' => array(),
2394
- 'kitagawa' => array(),
2395
- 'kitakata' => array(),
2396
- 'kitaura' => array(),
2397
- 'kobayashi' => array(),
2398
- 'kunitomi' => array(),
2399
- 'kushima' => array(),
2400
- 'mimata' => array(),
2401
- 'miyakonojo' => array(),
2402
- 'miyazaki' => array(),
2403
- 'morotsuka' => array(),
2404
- 'nichinan' => array(),
2405
- 'nishimera' => array(),
2406
- 'nobeoka' => array(),
2407
- 'saito' => array(),
2408
- 'shiiba' => array(),
2409
- 'shintomi' => array(),
2410
- 'takaharu' => array(),
2411
- 'takanabe' => array(),
2412
- 'takazaki' => array(),
2413
- 'tsuno' => array()),
2414
- 'nagano' => array('achi' => array(),
2415
- 'agematsu' => array(),
2416
- 'anan' => array(),
2417
- 'aoki' => array(),
2418
- 'asahi' => array(),
2419
- 'azumino' => array(),
2420
- 'chikuhoku' => array(),
2421
- 'chikuma' => array(),
2422
- 'chino' => array(),
2423
- 'fujimi' => array(),
2424
- 'hakuba' => array(),
2425
- 'hara' => array(),
2426
- 'hiraya' => array(),
2427
- 'iida' => array(),
2428
- 'iijima' => array(),
2429
- 'iiyama' => array(),
2430
- 'iizuna' => array(),
2431
- 'ikeda' => array(),
2432
- 'ikusaka' => array(),
2433
- 'ina' => array(),
2434
- 'karuizawa' => array(),
2435
- 'kawakami' => array(),
2436
- 'kiso' => array(),
2437
- 'kisofukushima' => array(),
2438
- 'kitaaiki' => array(),
2439
- 'komagane' => array(),
2440
- 'komoro' => array(),
2441
- 'matsukawa' => array(),
2442
- 'matsumoto' => array(),
2443
- 'miasa' => array(),
2444
- 'minamiaiki' => array(),
2445
- 'minamimaki' => array(),
2446
- 'minamiminowa' => array(),
2447
- 'minowa' => array(),
2448
- 'miyada' => array(),
2449
- 'miyota' => array(),
2450
- 'mochizuki' => array(),
2451
- 'nagano' => array(),
2452
- 'nagawa' => array(),
2453
- 'nagiso' => array(),
2454
- 'nakagawa' => array(),
2455
- 'nakano' => array(),
2456
- 'nozawaonsen' => array(),
2457
- 'obuse' => array(),
2458
- 'ogawa' => array(),
2459
- 'okaya' => array(),
2460
- 'omachi' => array(),
2461
- 'omi' => array(),
2462
- 'ookuwa' => array(),
2463
- 'ooshika' => array(),
2464
- 'otaki' => array(),
2465
- 'otari' => array(),
2466
- 'sakae' => array(),
2467
- 'sakaki' => array(),
2468
- 'saku' => array(),
2469
- 'sakuho' => array(),
2470
- 'shimosuwa' => array(),
2471
- 'shinanomachi' => array(),
2472
- 'shiojiri' => array(),
2473
- 'suwa' => array(),
2474
- 'suzaka' => array(),
2475
- 'takagi' => array(),
2476
- 'takamori' => array(),
2477
- 'takayama' => array(),
2478
- 'tateshina' => array(),
2479
- 'tatsuno' => array(),
2480
- 'togakushi' => array(),
2481
- 'togura' => array(),
2482
- 'tomi' => array(),
2483
- 'ueda' => array(),
2484
- 'wada' => array(),
2485
- 'yamagata' => array(),
2486
- 'yamanouchi' => array(),
2487
- 'yasaka' => array(),
2488
- 'yasuoka' => array()),
2489
- 'nagasaki' => array('chijiwa' => array(),
2490
- 'futsu' => array(),
2491
- 'goto' => array(),
2492
- 'hasami' => array(),
2493
- 'hirado' => array(),
2494
- 'iki' => array(),
2495
- 'isahaya' => array(),
2496
- 'kawatana' => array(),
2497
- 'kuchinotsu' => array(),
2498
- 'matsuura' => array(),
2499
- 'nagasaki' => array(),
2500
- 'obama' => array(),
2501
- 'omura' => array(),
2502
- 'oseto' => array(),
2503
- 'saikai' => array(),
2504
- 'sasebo' => array(),
2505
- 'seihi' => array(),
2506
- 'shimabara' => array(),
2507
- 'shinkamigoto' => array(),
2508
- 'togitsu' => array(),
2509
- 'tsushima' => array(),
2510
- 'unzen' => array()),
2511
- 'nara' => array('ando' => array(),
2512
- 'gose' => array(),
2513
- 'heguri' => array(),
2514
- 'higashiyoshino' => array(),
2515
- 'ikaruga' => array(),
2516
- 'ikoma' => array(),
2517
- 'kamikitayama' => array(),
2518
- 'kanmaki' => array(),
2519
- 'kashiba' => array(),
2520
- 'kashihara' => array(),
2521
- 'katsuragi' => array(),
2522
- 'kawai' => array(),
2523
- 'kawakami' => array(),
2524
- 'kawanishi' => array(),
2525
- 'koryo' => array(),
2526
- 'kurotaki' => array(),
2527
- 'mitsue' => array(),
2528
- 'miyake' => array(),
2529
- 'nara' => array(),
2530
- 'nosegawa' => array(),
2531
- 'oji' => array(),
2532
- 'ouda' => array(),
2533
- 'oyodo' => array(),
2534
- 'sakurai' => array(),
2535
- 'sango' => array(),
2536
- 'shimoichi' => array(),
2537
- 'shimokitayama' => array(),
2538
- 'shinjo' => array(),
2539
- 'soni' => array(),
2540
- 'takatori' => array(),
2541
- 'tawaramoto' => array(),
2542
- 'tenkawa' => array(),
2543
- 'tenri' => array(),
2544
- 'uda' => array(),
2545
- 'yamatokoriyama' => array(),
2546
- 'yamatotakada' => array(),
2547
- 'yamazoe' => array(),
2548
- 'yoshino' => array()),
2549
- 'niigata' => array('aga' => array(),
2550
- 'agano' => array(),
2551
- 'gosen' => array(),
2552
- 'itoigawa' => array(),
2553
- 'izumozaki' => array(),
2554
- 'joetsu' => array(),
2555
- 'kamo' => array(),
2556
- 'kariwa' => array(),
2557
- 'kashiwazaki' => array(),
2558
- 'minamiuonuma' => array(),
2559
- 'mitsuke' => array(),
2560
- 'muika' => array(),
2561
- 'murakami' => array(),
2562
- 'myoko' => array(),
2563
- 'nagaoka' => array(),
2564
- 'niigata' => array(),
2565
- 'ojiya' => array(),
2566
- 'omi' => array(),
2567
- 'sado' => array(),
2568
- 'sanjo' => array(),
2569
- 'seiro' => array(),
2570
- 'seirou' => array(),
2571
- 'sekikawa' => array(),
2572
- 'shibata' => array(),
2573
- 'tagami' => array(),
2574
- 'tainai' => array(),
2575
- 'tochio' => array(),
2576
- 'tokamachi' => array(),
2577
- 'tsubame' => array(),
2578
- 'tsunan' => array(),
2579
- 'uonuma' => array(),
2580
- 'yahiko' => array(),
2581
- 'yoita' => array(),
2582
- 'yuzawa' => array()),
2583
- 'oita' => array('beppu' => array(),
2584
- 'bungoono' => array(),
2585
- 'bungotakada' => array(),
2586
- 'hasama' => array(),
2587
- 'hiji' => array(),
2588
- 'himeshima' => array(),
2589
- 'hita' => array(),
2590
- 'kamitsue' => array(),
2591
- 'kokonoe' => array(),
2592
- 'kuju' => array(),
2593
- 'kunisaki' => array(),
2594
- 'kusu' => array(),
2595
- 'oita' => array(),
2596
- 'saiki' => array(),
2597
- 'taketa' => array(),
2598
- 'tsukumi' => array(),
2599
- 'usa' => array(),
2600
- 'usuki' => array(),
2601
- 'yufu' => array()),
2602
- 'okayama' => array('akaiwa' => array(),
2603
- 'asakuchi' => array(),
2604
- 'bizen' => array(),
2605
- 'hayashima' => array(),
2606
- 'ibara' => array(),
2607
- 'kagamino' => array(),
2608
- 'kasaoka' => array(),
2609
- 'kibichuo' => array(),
2610
- 'kumenan' => array(),
2611
- 'kurashiki' => array(),
2612
- 'maniwa' => array(),
2613
- 'misaki' => array(),
2614
- 'nagi' => array(),
2615
- 'niimi' => array(),
2616
- 'nishiawakura' => array(),
2617
- 'okayama' => array(),
2618
- 'satosho' => array(),
2619
- 'setouchi' => array(),
2620
- 'shinjo' => array(),
2621
- 'shoo' => array(),
2622
- 'soja' => array(),
2623
- 'takahashi' => array(),
2624
- 'tamano' => array(),
2625
- 'tsuyama' => array(),
2626
- 'wake' => array(),
2627
- 'yakage' => array()),
2628
- 'okinawa' => array('aguni' => array(),
2629
- 'ginowan' => array(),
2630
- 'ginoza' => array(),
2631
- 'gushikami' => array(),
2632
- 'haebaru' => array(),
2633
- 'higashi' => array(),
2634
- 'hirara' => array(),
2635
- 'iheya' => array(),
2636
- 'ishigaki' => array(),
2637
- 'ishikawa' => array(),
2638
- 'itoman' => array(),
2639
- 'izena' => array(),
2640
- 'kadena' => array(),
2641
- 'kin' => array(),
2642
- 'kitadaito' => array(),
2643
- 'kitanakagusuku' => array(),
2644
- 'kumejima' => array(),
2645
- 'kunigami' => array(),
2646
- 'minamidaito' => array(),
2647
- 'motobu' => array(),
2648
- 'nago' => array(),
2649
- 'naha' => array(),
2650
- 'nakagusuku' => array(),
2651
- 'nakijin' => array(),
2652
- 'nanjo' => array(),
2653
- 'nishihara' => array(),
2654
- 'ogimi' => array(),
2655
- 'okinawa' => array(),
2656
- 'onna' => array(),
2657
- 'shimoji' => array(),
2658
- 'taketomi' => array(),
2659
- 'tarama' => array(),
2660
- 'tokashiki' => array(),
2661
- 'tomigusuku' => array(),
2662
- 'tonaki' => array(),
2663
- 'urasoe' => array(),
2664
- 'uruma' => array(),
2665
- 'yaese' => array(),
2666
- 'yomitan' => array(),
2667
- 'yonabaru' => array(),
2668
- 'yonaguni' => array(),
2669
- 'zamami' => array()),
2670
- 'osaka' => array('abeno' => array(),
2671
- 'chihayaakasaka' => array(),
2672
- 'chuo' => array(),
2673
- 'daito' => array(),
2674
- 'fujiidera' => array(),
2675
- 'habikino' => array(),
2676
- 'hannan' => array(),
2677
- 'higashiosaka' => array(),
2678
- 'higashisumiyoshi' => array(),
2679
- 'higashiyodogawa' => array(),
2680
- 'hirakata' => array(),
2681
- 'ibaraki' => array(),
2682
- 'ikeda' => array(),
2683
- 'izumi' => array(),
2684
- 'izumiotsu' => array(),
2685
- 'izumisano' => array(),
2686
- 'kadoma' => array(),
2687
- 'kaizuka' => array(),
2688
- 'kanan' => array(),
2689
- 'kashiwara' => array(),
2690
- 'katano' => array(),
2691
- 'kawachinagano' => array(),
2692
- 'kishiwada' => array(),
2693
- 'kita' => array(),
2694
- 'kumatori' => array(),
2695
- 'matsubara' => array(),
2696
- 'minato' => array(),
2697
- 'minoh' => array(),
2698
- 'misaki' => array(),
2699
- 'moriguchi' => array(),
2700
- 'neyagawa' => array(),
2701
- 'nishi' => array(),
2702
- 'nose' => array(),
2703
- 'osakasayama' => array(),
2704
- 'sakai' => array(),
2705
- 'sayama' => array(),
2706
- 'sennan' => array(),
2707
- 'settsu' => array(),
2708
- 'shijonawate' => array(),
2709
- 'shimamoto' => array(),
2710
- 'suita' => array(),
2711
- 'tadaoka' => array(),
2712
- 'taishi' => array(),
2713
- 'tajiri' => array(),
2714
- 'takaishi' => array(),
2715
- 'takatsuki' => array(),
2716
- 'tondabayashi' => array(),
2717
- 'toyonaka' => array(),
2718
- 'toyono' => array(),
2719
- 'yao' => array()),
2720
- 'saga' => array('ariake' => array(),
2721
- 'arita' => array(),
2722
- 'fukudomi' => array(),
2723
- 'genkai' => array(),
2724
- 'hamatama' => array(),
2725
- 'hizen' => array(),
2726
- 'imari' => array(),
2727
- 'kamimine' => array(),
2728
- 'kanzaki' => array(),
2729
- 'karatsu' => array(),
2730
- 'kashima' => array(),
2731
- 'kitagata' => array(),
2732
- 'kitahata' => array(),
2733
- 'kiyama' => array(),
2734
- 'kouhoku' => array(),
2735
- 'kyuragi' => array(),
2736
- 'nishiarita' => array(),
2737
- 'ogi' => array(),
2738
- 'omachi' => array(),
2739
- 'ouchi' => array(),
2740
- 'saga' => array(),
2741
- 'shiroishi' => array(),
2742
- 'taku' => array(),
2743
- 'tara' => array(),
2744
- 'tosu' => array(),
2745
- 'yoshinogari' => array()),
2746
- 'saitama' => array('arakawa' => array(),
2747
- 'asaka' => array(),
2748
- 'chichibu' => array(),
2749
- 'fujimi' => array(),
2750
- 'fujimino' => array(),
2751
- 'fukaya' => array(),
2752
- 'hanno' => array(),
2753
- 'hanyu' => array(),
2754
- 'hasuda' => array(),
2755
- 'hatogaya' => array(),
2756
- 'hatoyama' => array(),
2757
- 'hidaka' => array(),
2758
- 'higashichichibu' => array(),
2759
- 'higashimatsuyama' => array(),
2760
- 'honjo' => array(),
2761
- 'ina' => array(),
2762
- 'iruma' => array(),
2763
- 'iwatsuki' => array(),
2764
- 'kamiizumi' => array(),
2765
- 'kamikawa' => array(),
2766
- 'kamisato' => array(),
2767
- 'kasukabe' => array(),
2768
- 'kawagoe' => array(),
2769
- 'kawaguchi' => array(),
2770
- 'kawajima' => array(),
2771
- 'kazo' => array(),
2772
- 'kitamoto' => array(),
2773
- 'koshigaya' => array(),
2774
- 'kounosu' => array(),
2775
- 'kuki' => array(),
2776
- 'kumagaya' => array(),
2777
- 'matsubushi' => array(),
2778
- 'minano' => array(),
2779
- 'misato' => array(),
2780
- 'miyashiro' => array(),
2781
- 'miyoshi' => array(),
2782
- 'moroyama' => array(),
2783
- 'nagatoro' => array(),
2784
- 'namegawa' => array(),
2785
- 'niiza' => array(),
2786
- 'ogano' => array(),
2787
- 'ogawa' => array(),
2788
- 'ogose' => array(),
2789
- 'okegawa' => array(),
2790
- 'omiya' => array(),
2791
- 'otaki' => array(),
2792
- 'ranzan' => array(),
2793
- 'ryokami' => array(),
2794
- 'saitama' => array(),
2795
- 'sakado' => array(),
2796
- 'satte' => array(),
2797
- 'sayama' => array(),
2798
- 'shiki' => array(),
2799
- 'shiraoka' => array(),
2800
- 'soka' => array(),
2801
- 'sugito' => array(),
2802
- 'toda' => array(),
2803
- 'tokigawa' => array(),
2804
- 'tokorozawa' => array(),
2805
- 'tsurugashima' => array(),
2806
- 'urawa' => array(),
2807
- 'warabi' => array(),
2808
- 'yashio' => array(),
2809
- 'yokoze' => array(),
2810
- 'yono' => array(),
2811
- 'yorii' => array(),
2812
- 'yoshida' => array(),
2813
- 'yoshikawa' => array(),
2814
- 'yoshimi' => array()),
2815
- 'shiga' => array('aisho' => array(),
2816
- 'gamo' => array(),
2817
- 'higashiomi' => array(),
2818
- 'hikone' => array(),
2819
- 'koka' => array(),
2820
- 'konan' => array(),
2821
- 'kosei' => array(),
2822
- 'koto' => array(),
2823
- 'kusatsu' => array(),
2824
- 'maibara' => array(),
2825
- 'moriyama' => array(),
2826
- 'nagahama' => array(),
2827
- 'nishiazai' => array(),
2828
- 'notogawa' => array(),
2829
- 'omihachiman' => array(),
2830
- 'otsu' => array(),
2831
- 'ritto' => array(),
2832
- 'ryuoh' => array(),
2833
- 'takashima' => array(),
2834
- 'takatsuki' => array(),
2835
- 'torahime' => array(),
2836
- 'toyosato' => array(),
2837
- 'yasu' => array()),
2838
- 'shimane' => array('akagi' => array(),
2839
- 'ama' => array(),
2840
- 'gotsu' => array(),
2841
- 'hamada' => array(),
2842
- 'higashiizumo' => array(),
2843
- 'hikawa' => array(),
2844
- 'hikimi' => array(),
2845
- 'izumo' => array(),
2846
- 'kakinoki' => array(),
2847
- 'masuda' => array(),
2848
- 'matsue' => array(),
2849
- 'misato' => array(),
2850
- 'nishinoshima' => array(),
2851
- 'ohda' => array(),
2852
- 'okinoshima' => array(),
2853
- 'okuizumo' => array(),
2854
- 'shimane' => array(),
2855
- 'tamayu' => array(),
2856
- 'tsuwano' => array(),
2857
- 'unnan' => array(),
2858
- 'yakumo' => array(),
2859
- 'yasugi' => array(),
2860
- 'yatsuka' => array()),
2861
- 'shizuoka' => array('arai' => array(),
2862
- 'atami' => array(),
2863
- 'fuji' => array(),
2864
- 'fujieda' => array(),
2865
- 'fujikawa' => array(),
2866
- 'fujinomiya' => array(),
2867
- 'fukuroi' => array(),
2868
- 'gotemba' => array(),
2869
- 'haibara' => array(),
2870
- 'hamamatsu' => array(),
2871
- 'higashiizu' => array(),
2872
- 'ito' => array(),
2873
- 'iwata' => array(),
2874
- 'izu' => array(),
2875
- 'izunokuni' => array(),
2876
- 'kakegawa' => array(),
2877
- 'kannami' => array(),
2878
- 'kawanehon' => array(),
2879
- 'kawazu' => array(),
2880
- 'kikugawa' => array(),
2881
- 'kosai' => array(),
2882
- 'makinohara' => array(),
2883
- 'matsuzaki' => array(),
2884
- 'minamiizu' => array(),
2885
- 'mishima' => array(),
2886
- 'morimachi' => array(),
2887
- 'nishiizu' => array(),
2888
- 'numazu' => array(),
2889
- 'omaezaki' => array(),
2890
- 'shimada' => array(),
2891
- 'shimizu' => array(),
2892
- 'shimoda' => array(),
2893
- 'shizuoka' => array(),
2894
- 'susono' => array(),
2895
- 'yaizu' => array(),
2896
- 'yoshida' => array()),
2897
- 'tochigi' => array('ashikaga' => array(),
2898
- 'bato' => array(),
2899
- 'haga' => array(),
2900
- 'ichikai' => array(),
2901
- 'iwafune' => array(),
2902
- 'kaminokawa' => array(),
2903
- 'kanuma' => array(),
2904
- 'karasuyama' => array(),
2905
- 'kuroiso' => array(),
2906
- 'mashiko' => array(),
2907
- 'mibu' => array(),
2908
- 'moka' => array(),
2909
- 'motegi' => array(),
2910
- 'nasu' => array(),
2911
- 'nasushiobara' => array(),
2912
- 'nikko' => array(),
2913
- 'nishikata' => array(),
2914
- 'nogi' => array(),
2915
- 'ohira' => array(),
2916
- 'ohtawara' => array(),
2917
- 'oyama' => array(),
2918
- 'sakura' => array(),
2919
- 'sano' => array(),
2920
- 'shimotsuke' => array(),
2921
- 'shioya' => array(),
2922
- 'takanezawa' => array(),
2923
- 'tochigi' => array(),
2924
- 'tsuga' => array(),
2925
- 'ujiie' => array(),
2926
- 'utsunomiya' => array(),
2927
- 'yaita' => array()),
2928
- 'tokushima' => array('aizumi' => array(),
2929
- 'anan' => array(),
2930
- 'ichiba' => array(),
2931
- 'itano' => array(),
2932
- 'kainan' => array(),
2933
- 'komatsushima' => array(),
2934
- 'matsushige' => array(),
2935
- 'mima' => array(),
2936
- 'minami' => array(),
2937
- 'miyoshi' => array(),
2938
- 'mugi' => array(),
2939
- 'nakagawa' => array(),
2940
- 'naruto' => array(),
2941
- 'sanagochi' => array(),
2942
- 'shishikui' => array(),
2943
- 'tokushima' => array(),
2944
- 'wajiki' => array()),
2945
- 'tokyo' => array('adachi' => array(),
2946
- 'akiruno' => array(),
2947
- 'akishima' => array(),
2948
- 'aogashima' => array(),
2949
- 'arakawa' => array(),
2950
- 'bunkyo' => array(),
2951
- 'chiyoda' => array(),
2952
- 'chofu' => array(),
2953
- 'chuo' => array(),
2954
- 'edogawa' => array(),
2955
- 'fuchu' => array(),
2956
- 'fussa' => array(),
2957
- 'hachijo' => array(),
2958
- 'hachioji' => array(),
2959
- 'hamura' => array(),
2960
- 'higashikurume' => array(),
2961
- 'higashimurayama' => array(),
2962
- 'higashiyamato' => array(),
2963
- 'hino' => array(),
2964
- 'hinode' => array(),
2965
- 'hinohara' => array(),
2966
- 'inagi' => array(),
2967
- 'itabashi' => array(),
2968
- 'katsushika' => array(),
2969
- 'kita' => array(),
2970
- 'kiyose' => array(),
2971
- 'kodaira' => array(),
2972
- 'koganei' => array(),
2973
- 'kokubunji' => array(),
2974
- 'komae' => array(),
2975
- 'koto' => array(),
2976
- 'kouzushima' => array(),
2977
- 'kunitachi' => array(),
2978
- 'machida' => array(),
2979
- 'meguro' => array(),
2980
- 'minato' => array(),
2981
- 'mitaka' => array(),
2982
- 'mizuho' => array(),
2983
- 'musashimurayama' => array(),
2984
- 'musashino' => array(),
2985
- 'nakano' => array(),
2986
- 'nerima' => array(),
2987
- 'ogasawara' => array(),
2988
- 'okutama' => array(),
2989
- 'ome' => array(),
2990
- 'oshima' => array(),
2991
- 'ota' => array(),
2992
- 'setagaya' => array(),
2993
- 'shibuya' => array(),
2994
- 'shinagawa' => array(),
2995
- 'shinjuku' => array(),
2996
- 'suginami' => array(),
2997
- 'sumida' => array(),
2998
- 'tachikawa' => array(),
2999
- 'taito' => array(),
3000
- 'tama' => array(),
3001
- 'toshima' => array()),
3002
- 'tottori' => array('chizu' => array(),
3003
- 'hino' => array(),
3004
- 'kawahara' => array(),
3005
- 'koge' => array(),
3006
- 'kotoura' => array(),
3007
- 'misasa' => array(),
3008
- 'nanbu' => array(),
3009
- 'nichinan' => array(),
3010
- 'sakaiminato' => array(),
3011
- 'tottori' => array(),
3012
- 'wakasa' => array(),
3013
- 'yazu' => array(),
3014
- 'yonago' => array()),
3015
- 'toyama' => array('asahi' => array(),
3016
- 'fuchu' => array(),
3017
- 'fukumitsu' => array(),
3018
- 'funahashi' => array(),
3019
- 'himi' => array(),
3020
- 'imizu' => array(),
3021
- 'inami' => array(),
3022
- 'johana' => array(),
3023
- 'kamiichi' => array(),
3024
- 'kurobe' => array(),
3025
- 'nakaniikawa' => array(),
3026
- 'namerikawa' => array(),
3027
- 'nanto' => array(),
3028
- 'nyuzen' => array(),
3029
- 'oyabe' => array(),
3030
- 'taira' => array(),
3031
- 'takaoka' => array(),
3032
- 'tateyama' => array(),
3033
- 'toga' => array(),
3034
- 'tonami' => array(),
3035
- 'toyama' => array(),
3036
- 'unazuki' => array(),
3037
- 'uozu' => array(),
3038
- 'yamada' => array()),
3039
- 'wakayama' => array('arida' => array(),
3040
- 'aridagawa' => array(),
3041
- 'gobo' => array(),
3042
- 'hashimoto' => array(),
3043
- 'hidaka' => array(),
3044
- 'hirogawa' => array(),
3045
- 'inami' => array(),
3046
- 'iwade' => array(),
3047
- 'kainan' => array(),
3048
- 'kamitonda' => array(),
3049
- 'katsuragi' => array(),
3050
- 'kimino' => array(),
3051
- 'kinokawa' => array(),
3052
- 'kitayama' => array(),
3053
- 'koya' => array(),
3054
- 'koza' => array(),
3055
- 'kozagawa' => array(),
3056
- 'kudoyama' => array(),
3057
- 'kushimoto' => array(),
3058
- 'mihama' => array(),
3059
- 'misato' => array(),
3060
- 'nachikatsuura' => array(),
3061
- 'shingu' => array(),
3062
- 'shirahama' => array(),
3063
- 'taiji' => array(),
3064
- 'tanabe' => array(),
3065
- 'wakayama' => array(),
3066
- 'yuasa' => array(),
3067
- 'yura' => array()),
3068
- 'yamagata' => array('asahi' => array(),
3069
- 'funagata' => array(),
3070
- 'higashine' => array(),
3071
- 'iide' => array(),
3072
- 'kahoku' => array(),
3073
- 'kaminoyama' => array(),
3074
- 'kaneyama' => array(),
3075
- 'kawanishi' => array(),
3076
- 'mamurogawa' => array(),
3077
- 'mikawa' => array(),
3078
- 'murayama' => array(),
3079
- 'nagai' => array(),
3080
- 'nakayama' => array(),
3081
- 'nanyo' => array(),
3082
- 'nishikawa' => array(),
3083
- 'obanazawa' => array(),
3084
- 'oe' => array(),
3085
- 'oguni' => array(),
3086
- 'ohkura' => array(),
3087
- 'oishida' => array(),
3088
- 'sagae' => array(),
3089
- 'sakata' => array(),
3090
- 'sakegawa' => array(),
3091
- 'shinjo' => array(),
3092
- 'shirataka' => array(),
3093
- 'shonai' => array(),
3094
- 'takahata' => array(),
3095
- 'tendo' => array(),
3096
- 'tozawa' => array(),
3097
- 'tsuruoka' => array(),
3098
- 'yamagata' => array(),
3099
- 'yamanobe' => array(),
3100
- 'yonezawa' => array(),
3101
- 'yuza' => array()),
3102
- 'yamaguchi' => array('abu' => array(),
3103
- 'hagi' => array(),
3104
- 'hikari' => array(),
3105
- 'hofu' => array(),
3106
- 'iwakuni' => array(),
3107
- 'kudamatsu' => array(),
3108
- 'mitou' => array(),
3109
- 'nagato' => array(),
3110
- 'oshima' => array(),
3111
- 'shimonoseki' => array(),
3112
- 'shunan' => array(),
3113
- 'tabuse' => array(),
3114
- 'tokuyama' => array(),
3115
- 'toyota' => array(),
3116
- 'ube' => array(),
3117
- 'yuu' => array()),
3118
- 'yamanashi' => array('chuo' => array(),
3119
- 'doshi' => array(),
3120
- 'fuefuki' => array(),
3121
- 'fujikawa' => array(),
3122
- 'fujikawaguchiko' => array(),
3123
- 'fujiyoshida' => array(),
3124
- 'hayakawa' => array(),
3125
- 'hokuto' => array(),
3126
- 'ichikawamisato' => array(),
3127
- 'kai' => array(),
3128
- 'kofu' => array(),
3129
- 'koshu' => array(),
3130
- 'kosuge' => array(),
3131
- 'minami-alps' => array(),
3132
- 'minobu' => array(),
3133
- 'nakamichi' => array(),
3134
- 'nanbu' => array(),
3135
- 'narusawa' => array(),
3136
- 'nirasaki' => array(),
3137
- 'nishikatsura' => array(),
3138
- 'oshino' => array(),
3139
- 'otsuki' => array(),
3140
- 'showa' => array(),
3141
- 'tabayama' => array(),
3142
- 'tsuru' => array(),
3143
- 'uenohara' => array(),
3144
- 'yamanakako' => array(),
3145
- 'yamanashi' => array()),
3146
- 'kawasaki' => array('*' => array(),
3147
- 'city' => array('!' => '')),
3148
- 'kitakyushu' => array('*' => array(),
3149
- 'city' => array('!' => '')),
3150
- 'kobe' => array('*' => array(),
3151
- 'city' => array('!' => '')),
3152
- 'nagoya' => array('*' => array(),
3153
- 'city' => array('!' => '')),
3154
- 'sapporo' => array('*' => array(),
3155
- 'city' => array('!' => '')),
3156
- 'sendai' => array('*' => array(),
3157
- 'city' => array('!' => '')),
3158
- 'yokohama' => array('*' => array(),
3159
- 'city' => array('!' => '')),
3160
- 'blogspot' => array()),
3161
- 'ke' => array('*' => array()),
3162
- 'kg' => array('org' => array(),
3163
- 'net' => array(),
3164
- 'com' => array(),
3165
- 'edu' => array(),
3166
- 'gov' => array(),
3167
- 'mil' => array()),
3168
- 'kh' => array('*' => array()),
3169
- 'ki' => array('edu' => array(),
3170
- 'biz' => array(),
3171
- 'net' => array(),
3172
- 'org' => array(),
3173
- 'gov' => array(),
3174
- 'info' => array(),
3175
- 'com' => array()),
3176
- 'km' => array('org' => array(),
3177
- 'nom' => array(),
3178
- 'gov' => array(),
3179
- 'prd' => array(),
3180
- 'tm' => array(),
3181
- 'edu' => array(),
3182
- 'mil' => array(),
3183
- 'ass' => array(),
3184
- 'com' => array(),
3185
- 'coop' => array(),
3186
- 'asso' => array(),
3187
- 'presse' => array(),
3188
- 'medecin' => array(),
3189
- 'notaires' => array(),
3190
- 'pharmaciens' => array(),
3191
- 'veterinaire' => array(),
3192
- 'gouv' => array()),
3193
- 'kn' => array('net' => array(),
3194
- 'org' => array(),
3195
- 'edu' => array(),
3196
- 'gov' => array()),
3197
- 'kp' => array('com' => array(),
3198
- 'edu' => array(),
3199
- 'gov' => array(),
3200
- 'org' => array(),
3201
- 'rep' => array(),
3202
- 'tra' => array()),
3203
- 'kr' => array('ac' => array(),
3204
- 'co' => array(),
3205
- 'es' => array(),
3206
- 'go' => array(),
3207
- 'hs' => array(),
3208
- 'kg' => array(),
3209
- 'mil' => array(),
3210
- 'ms' => array(),
3211
- 'ne' => array(),
3212
- 'or' => array(),
3213
- 'pe' => array(),
3214
- 're' => array(),
3215
- 'sc' => array(),
3216
- 'busan' => array(),
3217
- 'chungbuk' => array(),
3218
- 'chungnam' => array(),
3219
- 'daegu' => array(),
3220
- 'daejeon' => array(),
3221
- 'gangwon' => array(),
3222
- 'gwangju' => array(),
3223
- 'gyeongbuk' => array(),
3224
- 'gyeonggi' => array(),
3225
- 'gyeongnam' => array(),
3226
- 'incheon' => array(),
3227
- 'jeju' => array(),
3228
- 'jeonbuk' => array(),
3229
- 'jeonnam' => array(),
3230
- 'seoul' => array(),
3231
- 'ulsan' => array(),
3232
- 'blogspot' => array()),
3233
- 'kw' => array('*' => array()),
3234
- 'ky' => array('edu' => array(),
3235
- 'gov' => array(),
3236
- 'com' => array(),
3237
- 'org' => array(),
3238
- 'net' => array()),
3239
- 'kz' => array('org' => array(),
3240
- 'edu' => array(),
3241
- 'net' => array(),
3242
- 'gov' => array(),
3243
- 'mil' => array(),
3244
- 'com' => array()),
3245
- 'la' => array('int' => array(),
3246
- 'net' => array(),
3247
- 'info' => array(),
3248
- 'edu' => array(),
3249
- 'gov' => array(),
3250
- 'per' => array(),
3251
- 'com' => array(),
3252
- 'org' => array(),
3253
- 'c' => array()),
3254
- 'lb' => array('com' => array(),
3255
- 'edu' => array(),
3256
- 'gov' => array(),
3257
- 'net' => array(),
3258
- 'org' => array()),
3259
- 'lc' => array('com' => array(),
3260
- 'net' => array(),
3261
- 'co' => array(),
3262
- 'org' => array(),
3263
- 'edu' => array(),
3264
- 'gov' => array()),
3265
- 'li' => array(),
3266
- 'lk' => array('gov' => array(),
3267
- 'sch' => array(),
3268
- 'net' => array(),
3269
- 'int' => array(),
3270
- 'com' => array(),
3271
- 'org' => array(),
3272
- 'edu' => array(),
3273
- 'ngo' => array(),
3274
- 'soc' => array(),
3275
- 'web' => array(),
3276
- 'ltd' => array(),
3277
- 'assn' => array(),
3278
- 'grp' => array(),
3279
- 'hotel' => array()),
3280
- 'lr' => array('com' => array(),
3281
- 'edu' => array(),
3282
- 'gov' => array(),
3283
- 'org' => array(),
3284
- 'net' => array()),
3285
- 'ls' => array('co' => array(),
3286
- 'org' => array()),
3287
- 'lt' => array('gov' => array()),
3288
- 'lu' => array(),
3289
- 'lv' => array('com' => array(),
3290
- 'edu' => array(),
3291
- 'gov' => array(),
3292
- 'org' => array(),
3293
- 'mil' => array(),
3294
- 'id' => array(),
3295
- 'net' => array(),
3296
- 'asn' => array(),
3297
- 'conf' => array()),
3298
- 'ly' => array('com' => array(),
3299
- 'net' => array(),
3300
- 'gov' => array(),
3301
- 'plc' => array(),
3302
- 'edu' => array(),
3303
- 'sch' => array(),
3304
- 'med' => array(),
3305
- 'org' => array(),
3306
- 'id' => array()),
3307
- 'ma' => array('co' => array(),
3308
- 'net' => array(),
3309
- 'gov' => array(),
3310
- 'org' => array(),
3311
- 'ac' => array(),
3312
- 'press' => array()),
3313
- 'mc' => array('tm' => array(),
3314
- 'asso' => array()),
3315
- 'md' => array(),
3316
- 'me' => array('co' => array(),
3317
- 'net' => array(),
3318
- 'org' => array(),
3319
- 'edu' => array(),
3320
- 'ac' => array(),
3321
- 'gov' => array(),
3322
- 'its' => array(),
3323
- 'priv' => array()),
3324
- 'mg' => array('org' => array(),
3325
- 'nom' => array(),
3326
- 'gov' => array(),
3327
- 'prd' => array(),
3328
- 'tm' => array(),
3329
- 'edu' => array(),
3330
- 'mil' => array(),
3331
- 'com' => array()),
3332
- 'mh' => array(),
3333
- 'mil' => array(),
3334
- 'mk' => array('com' => array(),
3335
- 'org' => array(),
3336
- 'net' => array(),
3337
- 'edu' => array(),
3338
- 'gov' => array(),
3339
- 'inf' => array(),
3340
- 'name' => array()),
3341
- 'ml' => array('com' => array(),
3342
- 'edu' => array(),
3343
- 'gouv' => array(),
3344
- 'gov' => array(),
3345
- 'net' => array(),
3346
- 'org' => array(),
3347
- 'presse' => array()),
3348
- 'mm' => array('*' => array()),
3349
- 'mn' => array('gov' => array(),
3350
- 'edu' => array(),
3351
- 'org' => array(),
3352
- 'nyc' => array()),
3353
- 'mo' => array('com' => array(),
3354
- 'net' => array(),
3355
- 'org' => array(),
3356
- 'edu' => array(),
3357
- 'gov' => array()),
3358
- 'mobi' => array(),
3359
- 'mp' => array(),
3360
- 'mq' => array(),
3361
- 'mr' => array('gov' => array(),
3362
- 'blogspot' => array()),
3363
- 'ms' => array('com' => array(),
3364
- 'edu' => array(),
3365
- 'gov' => array(),
3366
- 'net' => array(),
3367
- 'org' => array()),
3368
- 'mt' => array('com' => array(),
3369
- 'edu' => array(),
3370
- 'net' => array(),
3371
- 'org' => array()),
3372
- 'mu' => array('com' => array(),
3373
- 'net' => array(),
3374
- 'org' => array(),
3375
- 'gov' => array(),
3376
- 'ac' => array(),
3377
- 'co' => array(),
3378
- 'or' => array()),
3379
- 'museum' => array('academy' => array(),
3380
- 'agriculture' => array(),
3381
- 'air' => array(),
3382
- 'airguard' => array(),
3383
- 'alabama' => array(),
3384
- 'alaska' => array(),
3385
- 'amber' => array(),
3386
- 'ambulance' => array(),
3387
- 'american' => array(),
3388
- 'americana' => array(),
3389
- 'americanantiques' => array(),
3390
- 'americanart' => array(),
3391
- 'amsterdam' => array(),
3392
- 'and' => array(),
3393
- 'annefrank' => array(),
3394
- 'anthro' => array(),
3395
- 'anthropology' => array(),
3396
- 'antiques' => array(),
3397
- 'aquarium' => array(),
3398
- 'arboretum' => array(),
3399
- 'archaeological' => array(),
3400
- 'archaeology' => array(),
3401
- 'architecture' => array(),
3402
- 'art' => array(),
3403
- 'artanddesign' => array(),
3404
- 'artcenter' => array(),
3405
- 'artdeco' => array(),
3406
- 'arteducation' => array(),
3407
- 'artgallery' => array(),
3408
- 'arts' => array(),
3409
- 'artsandcrafts' => array(),
3410
- 'asmatart' => array(),
3411
- 'assassination' => array(),
3412
- 'assisi' => array(),
3413
- 'association' => array(),
3414
- 'astronomy' => array(),
3415
- 'atlanta' => array(),
3416
- 'austin' => array(),
3417
- 'australia' => array(),
3418
- 'automotive' => array(),
3419
- 'aviation' => array(),
3420
- 'axis' => array(),
3421
- 'badajoz' => array(),
3422
- 'baghdad' => array(),
3423
- 'bahn' => array(),
3424
- 'bale' => array(),
3425
- 'baltimore' => array(),
3426
- 'barcelona' => array(),
3427
- 'baseball' => array(),
3428
- 'basel' => array(),
3429
- 'baths' => array(),
3430
- 'bauern' => array(),
3431
- 'beauxarts' => array(),
3432
- 'beeldengeluid' => array(),
3433
- 'bellevue' => array(),
3434
- 'bergbau' => array(),
3435
- 'berkeley' => array(),
3436
- 'berlin' => array(),
3437
- 'bern' => array(),
3438
- 'bible' => array(),
3439
- 'bilbao' => array(),
3440
- 'bill' => array(),
3441
- 'birdart' => array(),
3442
- 'birthplace' => array(),
3443
- 'bonn' => array(),
3444
- 'boston' => array(),
3445
- 'botanical' => array(),
3446
- 'botanicalgarden' => array(),
3447
- 'botanicgarden' => array(),
3448
- 'botany' => array(),
3449
- 'brandywinevalley' => array(),
3450
- 'brasil' => array(),
3451
- 'bristol' => array(),
3452
- 'british' => array(),
3453
- 'britishcolumbia' => array(),
3454
- 'broadcast' => array(),
3455
- 'brunel' => array(),
3456
- 'brussel' => array(),
3457
- 'brussels' => array(),
3458
- 'bruxelles' => array(),
3459
- 'building' => array(),
3460
- 'burghof' => array(),
3461
- 'bus' => array(),
3462
- 'bushey' => array(),
3463
- 'cadaques' => array(),
3464
- 'california' => array(),
3465
- 'cambridge' => array(),
3466
- 'can' => array(),
3467
- 'canada' => array(),
3468
- 'capebreton' => array(),
3469
- 'carrier' => array(),
3470
- 'cartoonart' => array(),
3471
- 'casadelamoneda' => array(),
3472
- 'castle' => array(),
3473
- 'castres' => array(),
3474
- 'celtic' => array(),
3475
- 'center' => array(),
3476
- 'chattanooga' => array(),
3477
- 'cheltenham' => array(),
3478
- 'chesapeakebay' => array(),
3479
- 'chicago' => array(),
3480
- 'children' => array(),
3481
- 'childrens' => array(),
3482
- 'childrensgarden' => array(),
3483
- 'chiropractic' => array(),
3484
- 'chocolate' => array(),
3485
- 'christiansburg' => array(),
3486
- 'cincinnati' => array(),
3487
- 'cinema' => array(),
3488
- 'circus' => array(),
3489
- 'civilisation' => array(),
3490
- 'civilization' => array(),
3491
- 'civilwar' => array(),
3492
- 'clinton' => array(),
3493
- 'clock' => array(),
3494
- 'coal' => array(),
3495
- 'coastaldefence' => array(),
3496
- 'cody' => array(),
3497
- 'coldwar' => array(),
3498
- 'collection' => array(),
3499
- 'colonialwilliamsburg' => array(),
3500
- 'coloradoplateau' => array(),
3501
- 'columbia' => array(),
3502
- 'columbus' => array(),
3503
- 'communication' => array(),
3504
- 'communications' => array(),
3505
- 'community' => array(),
3506
- 'computer' => array(),
3507
- 'computerhistory' => array(),
3508
- 'comunicações' => array(),
3509
- 'contemporary' => array(),
3510
- 'contemporaryart' => array(),
3511
- 'convent' => array(),
3512
- 'copenhagen' => array(),
3513
- 'corporation' => array(),
3514
- 'correios-e-telecomunicações' => array(),
3515
- 'corvette' => array(),
3516
- 'costume' => array(),
3517
- 'countryestate' => array(),
3518
- 'county' => array(),
3519
- 'crafts' => array(),
3520
- 'cranbrook' => array(),
3521
- 'creation' => array(),
3522
- 'cultural' => array(),
3523
- 'culturalcenter' => array(),
3524
- 'culture' => array(),
3525
- 'cyber' => array(),
3526
- 'cymru' => array(),
3527
- 'dali' => array(),
3528
- 'dallas' => array(),
3529
- 'database' => array(),
3530
- 'ddr' => array(),
3531
- 'decorativearts' => array(),
3532
- 'delaware' => array(),
3533
- 'delmenhorst' => array(),
3534
- 'denmark' => array(),
3535
- 'depot' => array(),
3536
- 'design' => array(),
3537
- 'detroit' => array(),
3538
- 'dinosaur' => array(),
3539
- 'discovery' => array(),
3540
- 'dolls' => array(),
3541
- 'donostia' => array(),
3542
- 'durham' => array(),
3543
- 'eastafrica' => array(),
3544
- 'eastcoast' => array(),
3545
- 'education' => array(),
3546
- 'educational' => array(),
3547
- 'egyptian' => array(),
3548
- 'eisenbahn' => array(),
3549
- 'elburg' => array(),
3550
- 'elvendrell' => array(),
3551
- 'embroidery' => array(),
3552
- 'encyclopedic' => array(),
3553
- 'england' => array(),
3554
- 'entomology' => array(),
3555
- 'environment' => array(),
3556
- 'environmentalconservation' => array(),
3557
- 'epilepsy' => array(),
3558
- 'essex' => array(),
3559
- 'estate' => array(),
3560
- 'ethnology' => array(),
3561
- 'exeter' => array(),
3562
- 'exhibition' => array(),
3563
- 'family' => array(),
3564
- 'farm' => array(),
3565
- 'farmequipment' => array(),
3566
- 'farmers' => array(),
3567
- 'farmstead' => array(),
3568
- 'field' => array(),
3569
- 'figueres' => array(),
3570
- 'filatelia' => array(),
3571
- 'film' => array(),
3572
- 'fineart' => array(),
3573
- 'finearts' => array(),
3574
- 'finland' => array(),
3575
- 'flanders' => array(),
3576
- 'florida' => array(),
3577
- 'force' => array(),
3578
- 'fortmissoula' => array(),
3579
- 'fortworth' => array(),
3580
- 'foundation' => array(),
3581
- 'francaise' => array(),
3582
- 'frankfurt' => array(),
3583
- 'franziskaner' => array(),
3584
- 'freemasonry' => array(),
3585
- 'freiburg' => array(),
3586
- 'fribourg' => array(),
3587
- 'frog' => array(),
3588
- 'fundacio' => array(),
3589
- 'furniture' => array(),
3590
- 'gallery' => array(),
3591
- 'garden' => array(),
3592
- 'gateway' => array(),
3593
- 'geelvinck' => array(),
3594
- 'gemological' => array(),
3595
- 'geology' => array(),
3596
- 'georgia' => array(),
3597
- 'giessen' => array(),
3598
- 'glas' => array(),
3599
- 'glass' => array(),
3600
- 'gorge' => array(),
3601
- 'grandrapids' => array(),
3602
- 'graz' => array(),
3603
- 'guernsey' => array(),
3604
- 'halloffame' => array(),
3605
- 'hamburg' => array(),
3606
- 'handson' => array(),
3607
- 'harvestcelebration' => array(),
3608
- 'hawaii' => array(),
3609
- 'health' => array(),
3610
- 'heimatunduhren' => array(),
3611
- 'hellas' => array(),
3612
- 'helsinki' => array(),
3613
- 'hembygdsforbund' => array(),
3614
- 'heritage' => array(),
3615
- 'histoire' => array(),
3616
- 'historical' => array(),
3617
- 'historicalsociety' => array(),
3618
- 'historichouses' => array(),
3619
- 'historisch' => array(),
3620
- 'historisches' => array(),
3621
- 'history' => array(),
3622
- 'historyofscience' => array(),
3623
- 'horology' => array(),
3624
- 'house' => array(),
3625
- 'humanities' => array(),
3626
- 'illustration' => array(),
3627
- 'imageandsound' => array(),
3628
- 'indian' => array(),
3629
- 'indiana' => array(),
3630
- 'indianapolis' => array(),
3631
- 'indianmarket' => array(),
3632
- 'intelligence' => array(),
3633
- 'interactive' => array(),
3634
- 'iraq' => array(),
3635
- 'iron' => array(),
3636
- 'isleofman' => array(),
3637
- 'jamison' => array(),
3638
- 'jefferson' => array(),
3639
- 'jerusalem' => array(),
3640
- 'jewelry' => array(),
3641
- 'jewish' => array(),
3642
- 'jewishart' => array(),
3643
- 'jfk' => array(),
3644
- 'journalism' => array(),
3645
- 'judaica' => array(),
3646
- 'judygarland' => array(),
3647
- 'juedisches' => array(),
3648
- 'juif' => array(),
3649
- 'karate' => array(),
3650
- 'karikatur' => array(),
3651
- 'kids' => array(),
3652
- 'koebenhavn' => array(),
3653
- 'koeln' => array(),
3654
- 'kunst' => array(),
3655
- 'kunstsammlung' => array(),
3656
- 'kunstunddesign' => array(),
3657
- 'labor' => array(),
3658
- 'labour' => array(),
3659
- 'lajolla' => array(),
3660
- 'lancashire' => array(),
3661
- 'landes' => array(),
3662
- 'lans' => array(),
3663
- 'läns' => array(),
3664
- 'larsson' => array(),
3665
- 'lewismiller' => array(),
3666
- 'lincoln' => array(),
3667
- 'linz' => array(),
3668
- 'living' => array(),
3669
- 'livinghistory' => array(),
3670
- 'localhistory' => array(),
3671
- 'london' => array(),
3672
- 'losangeles' => array(),
3673
- 'louvre' => array(),
3674
- 'loyalist' => array(),
3675
- 'lucerne' => array(),
3676
- 'luxembourg' => array(),
3677
- 'luzern' => array(),
3678
- 'mad' => array(),
3679
- 'madrid' => array(),
3680
- 'mallorca' => array(),
3681
- 'manchester' => array(),
3682
- 'mansion' => array(),
3683
- 'mansions' => array(),
3684
- 'manx' => array(),
3685
- 'marburg' => array(),
3686
- 'maritime' => array(),
3687
- 'maritimo' => array(),
3688
- 'maryland' => array(),
3689
- 'marylhurst' => array(),
3690
- 'media' => array(),
3691
- 'medical' => array(),
3692
- 'medizinhistorisches' => array(),
3693
- 'meeres' => array(),
3694
- 'memorial' => array(),
3695
- 'mesaverde' => array(),
3696
- 'michigan' => array(),
3697
- 'midatlantic' => array(),
3698
- 'military' => array(),
3699
- 'mill' => array(),
3700
- 'miners' => array(),
3701
- 'mining' => array(),
3702
- 'minnesota' => array(),
3703
- 'missile' => array(),
3704
- 'missoula' => array(),
3705
- 'modern' => array(),
3706
- 'moma' => array(),
3707
- 'money' => array(),
3708
- 'monmouth' => array(),
3709
- 'monticello' => array(),
3710
- 'montreal' => array(),
3711
- 'moscow' => array(),
3712
- 'motorcycle' => array(),
3713
- 'muenchen' => array(),
3714
- 'muenster' => array(),
3715
- 'mulhouse' => array(),
3716
- 'muncie' => array(),
3717
- 'museet' => array(),
3718
- 'museumcenter' => array(),
3719
- 'museumvereniging' => array(),
3720
- 'music' => array(),
3721
- 'national' => array(),
3722
- 'nationalfirearms' => array(),
3723
- 'nationalheritage' => array(),
3724
- 'nativeamerican' => array(),
3725
- 'naturalhistory' => array(),
3726
- 'naturalhistorymuseum' => array(),
3727
- 'naturalsciences' => array(),
3728
- 'nature' => array(),
3729
- 'naturhistorisches' => array(),
3730
- 'natuurwetenschappen' => array(),
3731
- 'naumburg' => array(),
3732
- 'naval' => array(),
3733
- 'nebraska' => array(),
3734
- 'neues' => array(),
3735
- 'newhampshire' => array(),
3736
- 'newjersey' => array(),
3737
- 'newmexico' => array(),
3738
- 'newport' => array(),
3739
- 'newspaper' => array(),
3740
- 'newyork' => array(),
3741
- 'niepce' => array(),
3742
- 'norfolk' => array(),
3743
- 'north' => array(),
3744
- 'nrw' => array(),
3745
- 'nuernberg' => array(),
3746
- 'nuremberg' => array(),
3747
- 'nyc' => array(),
3748
- 'nyny' => array(),
3749
- 'oceanographic' => array(),
3750
- 'oceanographique' => array(),
3751
- 'omaha' => array(),
3752
- 'online' => array(),
3753
- 'ontario' => array(),
3754
- 'openair' => array(),
3755
- 'oregon' => array(),
3756
- 'oregontrail' => array(),
3757
- 'otago' => array(),
3758
- 'oxford' => array(),
3759
- 'pacific' => array(),
3760
- 'paderborn' => array(),
3761
- 'palace' => array(),
3762
- 'paleo' => array(),
3763
- 'palmsprings' => array(),
3764
- 'panama' => array(),
3765
- 'paris' => array(),
3766
- 'pasadena' => array(),
3767
- 'pharmacy' => array(),
3768
- 'philadelphia' => array(),
3769
- 'philadelphiaarea' => array(),
3770
- 'philately' => array(),
3771
- 'phoenix' => array(),
3772
- 'photography' => array(),
3773
- 'pilots' => array(),
3774
- 'pittsburgh' => array(),
3775
- 'planetarium' => array(),
3776
- 'plantation' => array(),
3777
- 'plants' => array(),
3778
- 'plaza' => array(),
3779
- 'portal' => array(),
3780
- 'portland' => array(),
3781
- 'portlligat' => array(),
3782
- 'posts-and-telecommunications' => array(),
3783
- 'preservation' => array(),
3784
- 'presidio' => array(),
3785
- 'press' => array(),
3786
- 'project' => array(),
3787
- 'public' => array(),
3788
- 'pubol' => array(),
3789
- 'quebec' => array(),
3790
- 'railroad' => array(),
3791
- 'railway' => array(),
3792
- 'research' => array(),
3793
- 'resistance' => array(),
3794
- 'riodejaneiro' => array(),
3795
- 'rochester' => array(),
3796
- 'rockart' => array(),
3797
- 'roma' => array(),
3798
- 'russia' => array(),
3799
- 'saintlouis' => array(),
3800
- 'salem' => array(),
3801
- 'salvadordali' => array(),
3802
- 'salzburg' => array(),
3803
- 'sandiego' => array(),
3804
- 'sanfrancisco' => array(),
3805
- 'santabarbara' => array(),
3806
- 'santacruz' => array(),
3807
- 'santafe' => array(),
3808
- 'saskatchewan' => array(),
3809
- 'satx' => array(),
3810
- 'savannahga' => array(),
3811
- 'schlesisches' => array(),
3812
- 'schoenbrunn' => array(),
3813
- 'schokoladen' => array(),
3814
- 'school' => array(),
3815
- 'schweiz' => array(),
3816
- 'science' => array(),
3817
- 'scienceandhistory' => array(),
3818
- 'scienceandindustry' => array(),
3819
- 'sciencecenter' => array(),
3820
- 'sciencecenters' => array(),
3821
- 'science-fiction' => array(),
3822
- 'sciencehistory' => array(),
3823
- 'sciences' => array(),
3824
- 'sciencesnaturelles' => array(),
3825
- 'scotland' => array(),
3826
- 'seaport' => array(),
3827
- 'settlement' => array(),
3828
- 'settlers' => array(),
3829
- 'shell' => array(),
3830
- 'sherbrooke' => array(),
3831
- 'sibenik' => array(),
3832
- 'silk' => array(),
3833
- 'ski' => array(),
3834
- 'skole' => array(),
3835
- 'society' => array(),
3836
- 'sologne' => array(),
3837
- 'soundandvision' => array(),
3838
- 'southcarolina' => array(),
3839
- 'southwest' => array(),
3840
- 'space' => array(),
3841
- 'spy' => array(),
3842
- 'square' => array(),
3843
- 'stadt' => array(),
3844
- 'stalbans' => array(),
3845
- 'starnberg' => array(),
3846
- 'state' => array(),
3847
- 'stateofdelaware' => array(),
3848
- 'station' => array(),
3849
- 'steam' => array(),
3850
- 'steiermark' => array(),
3851
- 'stjohn' => array(),
3852
- 'stockholm' => array(),
3853
- 'stpetersburg' => array(),
3854
- 'stuttgart' => array(),
3855
- 'suisse' => array(),
3856
- 'surgeonshall' => array(),
3857
- 'surrey' => array(),
3858
- 'svizzera' => array(),
3859
- 'sweden' => array(),
3860
- 'sydney' => array(),
3861
- 'tank' => array(),
3862
- 'tcm' => array(),
3863
- 'technology' => array(),
3864
- 'telekommunikation' => array(),
3865
- 'television' => array(),
3866
- 'texas' => array(),
3867
- 'textile' => array(),
3868
- 'theater' => array(),
3869
- 'time' => array(),
3870
- 'timekeeping' => array(),
3871
- 'topology' => array(),
3872
- 'torino' => array(),
3873
- 'touch' => array(),
3874
- 'town' => array(),
3875
- 'transport' => array(),
3876
- 'tree' => array(),
3877
- 'trolley' => array(),
3878
- 'trust' => array(),
3879
- 'trustee' => array(),
3880
- 'uhren' => array(),
3881
- 'ulm' => array(),
3882
- 'undersea' => array(),
3883
- 'university' => array(),
3884
- 'usa' => array(),
3885
- 'usantiques' => array(),
3886
- 'usarts' => array(),
3887
- 'uscountryestate' => array(),
3888
- 'usculture' => array(),
3889
- 'usdecorativearts' => array(),
3890
- 'usgarden' => array(),
3891
- 'ushistory' => array(),
3892
- 'ushuaia' => array(),
3893
- 'uslivinghistory' => array(),
3894
- 'utah' => array(),
3895
- 'uvic' => array(),
3896
- 'valley' => array(),
3897
- 'vantaa' => array(),
3898
- 'versailles' => array(),
3899
- 'viking' => array(),
3900
- 'village' => array(),
3901
- 'virginia' => array(),
3902
- 'virtual' => array(),
3903
- 'virtuel' => array(),
3904
- 'vlaanderen' => array(),
3905
- 'volkenkunde' => array(),
3906
- 'wales' => array(),
3907
- 'wallonie' => array(),
3908
- 'war' => array(),
3909
- 'washingtondc' => array(),
3910
- 'watchandclock' => array(),
3911
- 'watch-and-clock' => array(),
3912
- 'western' => array(),
3913
- 'westfalen' => array(),
3914
- 'whaling' => array(),
3915
- 'wildlife' => array(),
3916
- 'williamsburg' => array(),
3917
- 'windmill' => array(),
3918
- 'workshop' => array(),
3919
- 'york' => array(),
3920
- 'yorkshire' => array(),
3921
- 'yosemite' => array(),
3922
- 'youth' => array(),
3923
- 'zoological' => array(),
3924
- 'zoology' => array(),
3925
- 'ירושלים' => array(),
3926
- 'иком' => array()),
3927
- 'mv' => array('aero' => array(),
3928
- 'biz' => array(),
3929
- 'com' => array(),
3930
- 'coop' => array(),
3931
- 'edu' => array(),
3932
- 'gov' => array(),
3933
- 'info' => array(),
3934
- 'int' => array(),
3935
- 'mil' => array(),
3936
- 'museum' => array(),
3937
- 'name' => array(),
3938
- 'net' => array(),
3939
- 'org' => array(),
3940
- 'pro' => array()),
3941
- 'mw' => array('ac' => array(),
3942
- 'biz' => array(),
3943
- 'co' => array(),
3944
- 'com' => array(),
3945
- 'coop' => array(),
3946
- 'edu' => array(),
3947
- 'gov' => array(),
3948
- 'int' => array(),
3949
- 'museum' => array(),
3950
- 'net' => array(),
3951
- 'org' => array()),
3952
- 'mx' => array('com' => array(),
3953
- 'org' => array(),
3954
- 'gob' => array(),
3955
- 'edu' => array(),
3956
- 'net' => array(),
3957
- 'blogspot' => array()),
3958
- 'my' => array('com' => array(),
3959
- 'net' => array(),
3960
- 'org' => array(),
3961
- 'gov' => array(),
3962
- 'edu' => array(),
3963
- 'mil' => array(),
3964
- 'name' => array()),
3965
- 'mz' => array('*' => array(),
3966
- 'teledata' => array('!' => '')),
3967
- 'na' => array('info' => array(),
3968
- 'pro' => array(),
3969
- 'name' => array(),
3970
- 'school' => array(),
3971
- 'or' => array(),
3972
- 'dr' => array(),
3973
- 'us' => array(),
3974
- 'mx' => array(),
3975
- 'ca' => array(),
3976
- 'in' => array(),
3977
- 'cc' => array(),
3978
- 'tv' => array(),
3979
- 'ws' => array(),
3980
- 'mobi' => array(),
3981
- 'co' => array(),
3982
- 'com' => array(),
3983
- 'org' => array()),
3984
- 'name' => array('her' => array('forgot' => array()),
3985
- 'his' => array('forgot' => array())),
3986
- 'nc' => array('asso' => array()),
3987
- 'ne' => array(),
3988
- 'net' => array('cloudfront' => array(),
3989
- 'gb' => array(),
3990
- 'hu' => array(),
3991
- 'jp' => array(),
3992
- 'se' => array(),
3993
- 'uk' => array(),
3994
- 'in' => array(),
3995
- 'at-band-camp' => array(),
3996
- 'blogdns' => array(),
3997
- 'broke-it' => array(),
3998
- 'buyshouses' => array(),
3999
- 'dnsalias' => array(),
4000
- 'dnsdojo' => array(),
4001
- 'does-it' => array(),
4002
- 'dontexist' => array(),
4003
- 'dynalias' => array(),
4004
- 'dynathome' => array(),
4005
- 'endofinternet' => array(),
4006
- 'from-az' => array(),
4007
- 'from-co' => array(),
4008
- 'from-la' => array(),
4009
- 'from-ny' => array(),
4010
- 'gets-it' => array(),
4011
- 'ham-radio-op' => array(),
4012
- 'homeftp' => array(),
4013
- 'homeip' => array(),
4014
- 'homelinux' => array(),
4015
- 'homeunix' => array(),
4016
- 'in-the-band' => array(),
4017
- 'is-a-chef' => array(),
4018
- 'is-a-geek' => array(),
4019
- 'isa-geek' => array(),
4020
- 'kicks-ass' => array(),
4021
- 'office-on-the' => array(),
4022
- 'podzone' => array(),
4023
- 'scrapper-site' => array(),
4024
- 'selfip' => array(),
4025
- 'sells-it' => array(),
4026
- 'servebbs' => array(),
4027
- 'serveftp' => array(),
4028
- 'thruhere' => array(),
4029
- 'webhop' => array(),
4030
- 'fastly' => array('ssl' => array('a' => array(),
4031
- 'b' => array(),
4032
- 'global' => array()),
4033
- 'prod' => array('a' => array(),
4034
- 'global' => array())),
4035
- 'azurewebsites' => array(),
4036
- 'azure-mobile' => array(),
4037
- 'cloudapp' => array(),
4038
- 'za' => array()),
4039
- 'nf' => array('com' => array(),
4040
- 'net' => array(),
4041
- 'per' => array(),
4042
- 'rec' => array(),
4043
- 'web' => array(),
4044
- 'arts' => array(),
4045
- 'firm' => array(),
4046
- 'info' => array(),
4047
- 'other' => array(),
4048
- 'store' => array()),
4049
- 'ng' => array('com' => array(),
4050
- 'edu' => array(),
4051
- 'name' => array(),
4052
- 'net' => array(),
4053
- 'org' => array(),
4054
- 'sch' => array(),
4055
- 'gov' => array(),
4056
- 'mil' => array(),
4057
- 'mobi' => array()),
4058
- 'ni' => array('*' => array()),
4059
- 'nl' => array('bv' => array(),
4060
- 'co' => array(),
4061
- 'blogspot' => array()),
4062
- 'no' => array('fhs' => array(),
4063
- 'vgs' => array(),
4064
- 'fylkesbibl' => array(),
4065
- 'folkebibl' => array(),
4066
- 'museum' => array(),
4067
- 'idrett' => array(),
4068
- 'priv' => array(),
4069
- 'mil' => array(),
4070
- 'stat' => array(),
4071
- 'dep' => array(),
4072
- 'kommune' => array(),
4073
- 'herad' => array(),
4074
- 'aa' => array('gs' => array()),
4075
- 'ah' => array('gs' => array()),
4076
- 'bu' => array('gs' => array()),
4077
- 'fm' => array('gs' => array()),
4078
- 'hl' => array('gs' => array()),
4079
- 'hm' => array('gs' => array()),
4080
- 'jan-mayen' => array('gs' => array()),
4081
- 'mr' => array('gs' => array()),
4082
- 'nl' => array('gs' => array()),
4083
- 'nt' => array('gs' => array()),
4084
- 'of' => array('gs' => array()),
4085
- 'ol' => array('gs' => array()),
4086
- 'oslo' => array('gs' => array()),
4087
- 'rl' => array('gs' => array()),
4088
- 'sf' => array('gs' => array()),
4089
- 'st' => array('gs' => array()),
4090
- 'svalbard' => array('gs' => array()),
4091
- 'tm' => array('gs' => array()),
4092
- 'tr' => array('gs' => array()),
4093
- 'va' => array('gs' => array()),
4094
- 'vf' => array('gs' => array()),
4095
- 'akrehamn' => array(),
4096
- 'åkrehamn' => array(),
4097
- 'algard' => array(),
4098
- 'ålgård' => array(),
4099
- 'arna' => array(),
4100
- 'brumunddal' => array(),
4101
- 'bryne' => array(),
4102
- 'bronnoysund' => array(),
4103
- 'brønnøysund' => array(),
4104
- 'drobak' => array(),
4105
- 'drøbak' => array(),
4106
- 'egersund' => array(),
4107
- 'fetsund' => array(),
4108
- 'floro' => array(),
4109
- 'florø' => array(),
4110
- 'fredrikstad' => array(),
4111
- 'hokksund' => array(),
4112
- 'honefoss' => array(),
4113
- 'hønefoss' => array(),
4114
- 'jessheim' => array(),
4115
- 'jorpeland' => array(),
4116
- 'jørpeland' => array(),
4117
- 'kirkenes' => array(),
4118
- 'kopervik' => array(),
4119
- 'krokstadelva' => array(),
4120
- 'langevag' => array(),
4121
- 'langevåg' => array(),
4122
- 'leirvik' => array(),
4123
- 'mjondalen' => array(),
4124
- 'mjøndalen' => array(),
4125
- 'mo-i-rana' => array(),
4126
- 'mosjoen' => array(),
4127
- 'mosjøen' => array(),
4128
- 'nesoddtangen' => array(),
4129
- 'orkanger' => array(),
4130
- 'osoyro' => array(),
4131
- 'osøyro' => array(),
4132
- 'raholt' => array(),
4133
- 'råholt' => array(),
4134
- 'sandnessjoen' => array(),
4135
- 'sandnessjøen' => array(),
4136
- 'skedsmokorset' => array(),
4137
- 'slattum' => array(),
4138
- 'spjelkavik' => array(),
4139
- 'stathelle' => array(),
4140
- 'stavern' => array(),
4141
- 'stjordalshalsen' => array(),
4142
- 'stjørdalshalsen' => array(),
4143
- 'tananger' => array(),
4144
- 'tranby' => array(),
4145
- 'vossevangen' => array(),
4146
- 'afjord' => array(),
4147
- 'åfjord' => array(),
4148
- 'agdenes' => array(),
4149
- 'al' => array(),
4150
- 'ål' => array(),
4151
- 'alesund' => array(),
4152
- 'ålesund' => array(),
4153
- 'alstahaug' => array(),
4154
- 'alta' => array(),
4155
- 'áltá' => array(),
4156
- 'alaheadju' => array(),
4157
- 'álaheadju' => array(),
4158
- 'alvdal' => array(),
4159
- 'amli' => array(),
4160
- 'åmli' => array(),
4161
- 'amot' => array(),
4162
- 'åmot' => array(),
4163
- 'andebu' => array(),
4164
- 'andoy' => array(),
4165
- 'andøy' => array(),
4166
- 'andasuolo' => array(),
4167
- 'ardal' => array(),
4168
- 'årdal' => array(),
4169
- 'aremark' => array(),
4170
- 'arendal' => array(),
4171
- 'ås' => array(),
4172
- 'aseral' => array(),
4173
- 'åseral' => array(),
4174
- 'asker' => array(),
4175
- 'askim' => array(),
4176
- 'askvoll' => array(),
4177
- 'askoy' => array(),
4178
- 'askøy' => array(),
4179
- 'asnes' => array(),
4180
- 'åsnes' => array(),
4181
- 'audnedaln' => array(),
4182
- 'aukra' => array(),
4183
- 'aure' => array(),
4184
- 'aurland' => array(),
4185
- 'aurskog-holand' => array(),
4186
- 'aurskog-høland' => array(),
4187
- 'austevoll' => array(),
4188
- 'austrheim' => array(),
4189
- 'averoy' => array(),
4190
- 'averøy' => array(),
4191
- 'balestrand' => array(),
4192
- 'ballangen' => array(),
4193
- 'balat' => array(),
4194
- 'bálát' => array(),
4195
- 'balsfjord' => array(),
4196
- 'bahccavuotna' => array(),
4197
- 'báhccavuotna' => array(),
4198
- 'bamble' => array(),
4199
- 'bardu' => array(),
4200
- 'beardu' => array(),
4201
- 'beiarn' => array(),
4202
- 'bajddar' => array(),
4203
- 'bájddar' => array(),
4204
- 'baidar' => array(),
4205
- 'báidár' => array(),
4206
- 'berg' => array(),
4207
- 'bergen' => array(),
4208
- 'berlevag' => array(),
4209
- 'berlevåg' => array(),
4210
- 'bearalvahki' => array(),
4211
- 'bearalváhki' => array(),
4212
- 'bindal' => array(),
4213
- 'birkenes' => array(),
4214
- 'bjarkoy' => array(),
4215
- 'bjarkøy' => array(),
4216
- 'bjerkreim' => array(),
4217
- 'bjugn' => array(),
4218
- 'bodo' => array(),
4219
- 'bodø' => array(),
4220
- 'badaddja' => array(),
4221
- 'bådåddjå' => array(),
4222
- 'budejju' => array(),
4223
- 'bokn' => array(),
4224
- 'bremanger' => array(),
4225
- 'bronnoy' => array(),
4226
- 'brønnøy' => array(),
4227
- 'bygland' => array(),
4228
- 'bykle' => array(),
4229
- 'barum' => array(),
4230
- 'bærum' => array(),
4231
- 'telemark' => array('bo' => array(),
4232
- 'bø' => array()),
4233
- 'nordland' => array('bo' => array(),
4234
- 'bø' => array(),
4235
- 'heroy' => array(),
4236
- 'herøy' => array()),
4237
- 'bievat' => array(),
4238
- 'bievát' => array(),
4239
- 'bomlo' => array(),
4240
- 'bømlo' => array(),
4241
- 'batsfjord' => array(),
4242
- 'båtsfjord' => array(),
4243
- 'bahcavuotna' => array(),
4244
- 'báhcavuotna' => array(),
4245
- 'dovre' => array(),
4246
- 'drammen' => array(),
4247
- 'drangedal' => array(),
4248
- 'dyroy' => array(),
4249
- 'dyrøy' => array(),
4250
- 'donna' => array(),
4251
- 'dønna' => array(),
4252
- 'eid' => array(),
4253
- 'eidfjord' => array(),
4254
- 'eidsberg' => array(),
4255
- 'eidskog' => array(),
4256
- 'eidsvoll' => array(),
4257
- 'eigersund' => array(),
4258
- 'elverum' => array(),
4259
- 'enebakk' => array(),
4260
- 'engerdal' => array(),
4261
- 'etne' => array(),
4262
- 'etnedal' => array(),
4263
- 'evenes' => array(),
4264
- 'evenassi' => array(),
4265
- 'evenášši' => array(),
4266
- 'evje-og-hornnes' => array(),
4267
- 'farsund' => array(),
4268
- 'fauske' => array(),
4269
- 'fuossko' => array(),
4270
- 'fuoisku' => array(),
4271
- 'fedje' => array(),
4272
- 'fet' => array(),
4273
- 'finnoy' => array(),
4274
- 'finnøy' => array(),
4275
- 'fitjar' => array(),
4276
- 'fjaler' => array(),
4277
- 'fjell' => array(),
4278
- 'flakstad' => array(),
4279
- 'flatanger' => array(),
4280
- 'flekkefjord' => array(),
4281
- 'flesberg' => array(),
4282
- 'flora' => array(),
4283
- 'fla' => array(),
4284
- 'flå' => array(),
4285
- 'folldal' => array(),
4286
- 'forsand' => array(),
4287
- 'fosnes' => array(),
4288
- 'frei' => array(),
4289
- 'frogn' => array(),
4290
- 'froland' => array(),
4291
- 'frosta' => array(),
4292
- 'frana' => array(),
4293
- 'fræna' => array(),
4294
- 'froya' => array(),
4295
- 'frøya' => array(),
4296
- 'fusa' => array(),
4297
- 'fyresdal' => array(),
4298
- 'forde' => array(),
4299
- 'førde' => array(),
4300
- 'gamvik' => array(),
4301
- 'gangaviika' => array(),
4302
- 'gáŋgaviika' => array(),
4303
- 'gaular' => array(),
4304
- 'gausdal' => array(),
4305
- 'gildeskal' => array(),
4306
- 'gildeskål' => array(),
4307
- 'giske' => array(),
4308
- 'gjemnes' => array(),
4309
- 'gjerdrum' => array(),
4310
- 'gjerstad' => array(),
4311
- 'gjesdal' => array(),
4312
- 'gjovik' => array(),
4313
- 'gjøvik' => array(),
4314
- 'gloppen' => array(),
4315
- 'gol' => array(),
4316
- 'gran' => array(),
4317
- 'grane' => array(),
4318
- 'granvin' => array(),
4319
- 'gratangen' => array(),
4320
- 'grimstad' => array(),
4321
- 'grong' => array(),
4322
- 'kraanghke' => array(),
4323
- 'kråanghke' => array(),
4324
- 'grue' => array(),
4325
- 'gulen' => array(),
4326
- 'hadsel' => array(),
4327
- 'halden' => array(),
4328
- 'halsa' => array(),
4329
- 'hamar' => array(),
4330
- 'hamaroy' => array(),
4331
- 'habmer' => array(),
4332
- 'hábmer' => array(),
4333
- 'hapmir' => array(),
4334
- 'hápmir' => array(),
4335
- 'hammerfest' => array(),
4336
- 'hammarfeasta' => array(),
4337
- 'hámmárfeasta' => array(),
4338
- 'haram' => array(),
4339
- 'hareid' => array(),
4340
- 'harstad' => array(),
4341
- 'hasvik' => array(),
4342
- 'aknoluokta' => array(),
4343
- 'ákŋoluokta' => array(),
4344
- 'hattfjelldal' => array(),
4345
- 'aarborte' => array(),
4346
- 'haugesund' => array(),
4347
- 'hemne' => array(),
4348
- 'hemnes' => array(),
4349
- 'hemsedal' => array(),
4350
- 'more-og-romsdal' => array('heroy' => array(),
4351
- 'sande' => array()),
4352
- 'møre-og-romsdal' => array('herøy' => array(),
4353
- 'sande' => array()),
4354
- 'hitra' => array(),
4355
- 'hjartdal' => array(),
4356
- 'hjelmeland' => array(),
4357
- 'hobol' => array(),
4358
- 'hobøl' => array(),
4359
- 'hof' => array(),
4360
- 'hol' => array(),
4361
- 'hole' => array(),
4362
- 'holmestrand' => array(),
4363
- 'holtalen' => array(),
4364
- 'holtålen' => array(),
4365
- 'hornindal' => array(),
4366
- 'horten' => array(),
4367
- 'hurdal' => array(),
4368
- 'hurum' => array(),
4369
- 'hvaler' => array(),
4370
- 'hyllestad' => array(),
4371
- 'hagebostad' => array(),
4372
- 'hægebostad' => array(),
4373
- 'hoyanger' => array(),
4374
- 'høyanger' => array(),
4375
- 'hoylandet' => array(),
4376
- 'høylandet' => array(),
4377
- 'ha' => array(),
4378
- 'hå' => array(),
4379
- 'ibestad' => array(),
4380
- 'inderoy' => array(),
4381
- 'inderøy' => array(),
4382
- 'iveland' => array(),
4383
- 'jevnaker' => array(),
4384
- 'jondal' => array(),
4385
- 'jolster' => array(),
4386
- 'jølster' => array(),
4387
- 'karasjok' => array(),
4388
- 'karasjohka' => array(),
4389
- 'kárášjohka' => array(),
4390
- 'karlsoy' => array(),
4391
- 'galsa' => array(),
4392
- 'gálsá' => array(),
4393
- 'karmoy' => array(),
4394
- 'karmøy' => array(),
4395
- 'kautokeino' => array(),
4396
- 'guovdageaidnu' => array(),
4397
- 'klepp' => array(),
4398
- 'klabu' => array(),
4399
- 'klæbu' => array(),
4400
- 'kongsberg' => array(),
4401
- 'kongsvinger' => array(),
4402
- 'kragero' => array(),
4403
- 'kragerø' => array(),
4404
- 'kristiansand' => array(),
4405
- 'kristiansund' => array(),
4406
- 'krodsherad' => array(),
4407
- 'krødsherad' => array(),
4408
- 'kvalsund' => array(),
4409
- 'rahkkeravju' => array(),
4410
- 'ráhkkerávju' => array(),
4411
- 'kvam' => array(),
4412
- 'kvinesdal' => array(),
4413
- 'kvinnherad' => array(),
4414
- 'kviteseid' => array(),
4415
- 'kvitsoy' => array(),
4416
- 'kvitsøy' => array(),
4417
- 'kvafjord' => array(),
4418
- 'kvæfjord' => array(),
4419
- 'giehtavuoatna' => array(),
4420
- 'kvanangen' => array(),
4421
- 'kvænangen' => array(),
4422
- 'navuotna' => array(),
4423
- 'návuotna' => array(),
4424
- 'kafjord' => array(),
4425
- 'kåfjord' => array(),
4426
- 'gaivuotna' => array(),
4427
- 'gáivuotna' => array(),
4428
- 'larvik' => array(),
4429
- 'lavangen' => array(),
4430
- 'lavagis' => array(),
4431
- 'loabat' => array(),
4432
- 'loabát' => array(),
4433
- 'lebesby' => array(),
4434
- 'davvesiida' => array(),
4435
- 'leikanger' => array(),
4436
- 'leirfjord' => array(),
4437
- 'leka' => array(),
4438
- 'leksvik' => array(),
4439
- 'lenvik' => array(),
4440
- 'leangaviika' => array(),
4441
- 'leaŋgaviika' => array(),
4442
- 'lesja' => array(),
4443
- 'levanger' => array(),
4444
- 'lier' => array(),
4445
- 'lierne' => array(),
4446
- 'lillehammer' => array(),
4447
- 'lillesand' => array(),
4448
- 'lindesnes' => array(),
4449
- 'lindas' => array(),
4450
- 'lindås' => array(),
4451
- 'lom' => array(),
4452
- 'loppa' => array(),
4453
- 'lahppi' => array(),
4454
- 'láhppi' => array(),
4455
- 'lund' => array(),
4456
- 'lunner' => array(),
4457
- 'luroy' => array(),
4458
- 'lurøy' => array(),
4459
- 'luster' => array(),
4460
- 'lyngdal' => array(),
4461
- 'lyngen' => array(),
4462
- 'ivgu' => array(),
4463
- 'lardal' => array(),
4464
- 'lerdal' => array(),
4465
- 'lærdal' => array(),
4466
- 'lodingen' => array(),
4467
- 'lødingen' => array(),
4468
- 'lorenskog' => array(),
4469
- 'lørenskog' => array(),
4470
- 'loten' => array(),
4471
- 'løten' => array(),
4472
- 'malvik' => array(),
4473
- 'masoy' => array(),
4474
- 'måsøy' => array(),
4475
- 'muosat' => array(),
4476
- 'muosát' => array(),
4477
- 'mandal' => array(),
4478
- 'marker' => array(),
4479
- 'marnardal' => array(),
4480
- 'masfjorden' => array(),
4481
- 'meland' => array(),
4482
- 'meldal' => array(),
4483
- 'melhus' => array(),
4484
- 'meloy' => array(),
4485
- 'meløy' => array(),
4486
- 'meraker' => array(),
4487
- 'meråker' => array(),
4488
- 'moareke' => array(),
4489
- 'moåreke' => array(),
4490
- 'midsund' => array(),
4491
- 'midtre-gauldal' => array(),
4492
- 'modalen' => array(),
4493
- 'modum' => array(),
4494
- 'molde' => array(),
4495
- 'moskenes' => array(),
4496
- 'moss' => array(),
4497
- 'mosvik' => array(),
4498
- 'malselv' => array(),
4499
- 'målselv' => array(),
4500
- 'malatvuopmi' => array(),
4501
- 'málatvuopmi' => array(),
4502
- 'namdalseid' => array(),
4503
- 'aejrie' => array(),
4504
- 'namsos' => array(),
4505
- 'namsskogan' => array(),
4506
- 'naamesjevuemie' => array(),
4507
- 'nååmesjevuemie' => array(),
4508
- 'laakesvuemie' => array(),
4509
- 'nannestad' => array(),
4510
- 'narvik' => array(),
4511
- 'narviika' => array(),
4512
- 'naustdal' => array(),
4513
- 'nedre-eiker' => array(),
4514
- 'akershus' => array('nes' => array()),
4515
- 'buskerud' => array('nes' => array()),
4516
- 'nesna' => array(),
4517
- 'nesodden' => array(),
4518
- 'nesseby' => array(),
4519
- 'unjarga' => array(),
4520
- 'unjárga' => array(),
4521
- 'nesset' => array(),
4522
- 'nissedal' => array(),
4523
- 'nittedal' => array(),
4524
- 'nord-aurdal' => array(),
4525
- 'nord-fron' => array(),
4526
- 'nord-odal' => array(),
4527
- 'norddal' => array(),
4528
- 'nordkapp' => array(),
4529
- 'davvenjarga' => array(),
4530
- 'davvenjárga' => array(),
4531
- 'nordre-land' => array(),
4532
- 'nordreisa' => array(),
4533
- 'raisa' => array(),
4534
- 'ráisa' => array(),
4535
- 'nore-og-uvdal' => array(),
4536
- 'notodden' => array(),
4537
- 'naroy' => array(),
4538
- 'nærøy' => array(),
4539
- 'notteroy' => array(),
4540
- 'nøtterøy' => array(),
4541
- 'odda' => array(),
4542
- 'oksnes' => array(),
4543
- 'øksnes' => array(),
4544
- 'oppdal' => array(),
4545
- 'oppegard' => array(),
4546
- 'oppegård' => array(),
4547
- 'orkdal' => array(),
4548
- 'orland' => array(),
4549
- 'ørland' => array(),
4550
- 'orskog' => array(),
4551
- 'ørskog' => array(),
4552
- 'orsta' => array(),
4553
- 'ørsta' => array(),
4554
- 'hedmark' => array('os' => array(),
4555
- 'valer' => array(),
4556
- 'våler' => array()),
4557
- 'hordaland' => array('os' => array()),
4558
- 'osen' => array(),
4559
- 'osteroy' => array(),
4560
- 'osterøy' => array(),
4561
- 'ostre-toten' => array(),
4562
- 'østre-toten' => array(),
4563
- 'overhalla' => array(),
4564
- 'ovre-eiker' => array(),
4565
- 'øvre-eiker' => array(),
4566
- 'oyer' => array(),
4567
- 'øyer' => array(),
4568
- 'oygarden' => array(),
4569
- 'øygarden' => array(),
4570
- 'oystre-slidre' => array(),
4571
- 'øystre-slidre' => array(),
4572
- 'porsanger' => array(),
4573
- 'porsangu' => array(),
4574
- 'porsáŋgu' => array(),
4575
- 'porsgrunn' => array(),
4576
- 'radoy' => array(),
4577
- 'radøy' => array(),
4578
- 'rakkestad' => array(),
4579
- 'rana' => array(),
4580
- 'ruovat' => array(),
4581
- 'randaberg' => array(),
4582
- 'rauma' => array(),
4583
- 'rendalen' => array(),
4584
- 'rennebu' => array(),
4585
- 'rennesoy' => array(),
4586
- 'rennesøy' => array(),
4587
- 'rindal' => array(),
4588
- 'ringebu' => array(),
4589
- 'ringerike' => array(),
4590
- 'ringsaker' => array(),
4591
- 'rissa' => array(),
4592
- 'risor' => array(),
4593
- 'risør' => array(),
4594
- 'roan' => array(),
4595
- 'rollag' => array(),
4596
- 'rygge' => array(),
4597
- 'ralingen' => array(),
4598
- 'rælingen' => array(),
4599
- 'rodoy' => array(),
4600
- 'rødøy' => array(),
4601
- 'romskog' => array(),
4602
- 'rømskog' => array(),
4603
- 'roros' => array(),
4604
- 'røros' => array(),
4605
- 'rost' => array(),
4606
- 'røst' => array(),
4607
- 'royken' => array(),
4608
- 'røyken' => array(),
4609
- 'royrvik' => array(),
4610
- 'røyrvik' => array(),
4611
- 'rade' => array(),
4612
- 'råde' => array(),
4613
- 'salangen' => array(),
4614
- 'siellak' => array(),
4615
- 'saltdal' => array(),
4616
- 'salat' => array(),
4617
- 'sálát' => array(),
4618
- 'sálat' => array(),
4619
- 'samnanger' => array(),
4620
- 'vestfold' => array('sande' => array()),
4621
- 'sandefjord' => array(),
4622
- 'sandnes' => array(),
4623
- 'sandoy' => array(),
4624
- 'sandøy' => array(),
4625
- 'sarpsborg' => array(),
4626
- 'sauda' => array(),
4627
- 'sauherad' => array(),
4628
- 'sel' => array(),
4629
- 'selbu' => array(),
4630
- 'selje' => array(),
4631
- 'seljord' => array(),
4632
- 'sigdal' => array(),
4633
- 'siljan' => array(),
4634
- 'sirdal' => array(),
4635
- 'skaun' => array(),
4636
- 'skedsmo' => array(),
4637
- 'ski' => array(),
4638
- 'skien' => array(),
4639
- 'skiptvet' => array(),
4640
- 'skjervoy' => array(),
4641
- 'skjervøy' => array(),
4642
- 'skierva' => array(),
4643
- 'skiervá' => array(),
4644
- 'skjak' => array(),
4645
- 'skjåk' => array(),
4646
- 'skodje' => array(),
4647
- 'skanland' => array(),
4648
- 'skånland' => array(),
4649
- 'skanit' => array(),
4650
- 'skánit' => array(),
4651
- 'smola' => array(),
4652
- 'smøla' => array(),
4653
- 'snillfjord' => array(),
4654
- 'snasa' => array(),
4655
- 'snåsa' => array(),
4656
- 'snoasa' => array(),
4657
- 'snaase' => array(),
4658
- 'snåase' => array(),
4659
- 'sogndal' => array(),
4660
- 'sokndal' => array(),
4661
- 'sola' => array(),
4662
- 'solund' => array(),
4663
- 'songdalen' => array(),
4664
- 'sortland' => array(),
4665
- 'spydeberg' => array(),
4666
- 'stange' => array(),
4667
- 'stavanger' => array(),
4668
- 'steigen' => array(),
4669
- 'steinkjer' => array(),
4670
- 'stjordal' => array(),
4671
- 'stjørdal' => array(),
4672
- 'stokke' => array(),
4673
- 'stor-elvdal' => array(),
4674
- 'stord' => array(),
4675
- 'stordal' => array(),
4676
- 'storfjord' => array(),
4677
- 'omasvuotna' => array(),
4678
- 'strand' => array(),
4679
- 'stranda' => array(),
4680
- 'stryn' => array(),
4681
- 'sula' => array(),
4682
- 'suldal' => array(),
4683
- 'sund' => array(),
4684
- 'sunndal' => array(),
4685
- 'surnadal' => array(),
4686
- 'sveio' => array(),
4687
- 'svelvik' => array(),
4688
- 'sykkylven' => array(),
4689
- 'sogne' => array(),
4690
- 'søgne' => array(),
4691
- 'somna' => array(),
4692
- 'sømna' => array(),
4693
- 'sondre-land' => array(),
4694
- 'søndre-land' => array(),
4695
- 'sor-aurdal' => array(),
4696
- 'sør-aurdal' => array(),
4697
- 'sor-fron' => array(),
4698
- 'sør-fron' => array(),
4699
- 'sor-odal' => array(),
4700
- 'sør-odal' => array(),
4701
- 'sor-varanger' => array(),
4702
- 'sør-varanger' => array(),
4703
- 'matta-varjjat' => array(),
4704
- 'mátta-várjjat' => array(),
4705
- 'sorfold' => array(),
4706
- 'sørfold' => array(),
4707
- 'sorreisa' => array(),
4708
- 'sørreisa' => array(),
4709
- 'sorum' => array(),
4710
- 'sørum' => array(),
4711
- 'tana' => array(),
4712
- 'deatnu' => array(),
4713
- 'time' => array(),
4714
- 'tingvoll' => array(),
4715
- 'tinn' => array(),
4716
- 'tjeldsund' => array(),
4717
- 'dielddanuorri' => array(),
4718
- 'tjome' => array(),
4719
- 'tjøme' => array(),
4720
- 'tokke' => array(),
4721
- 'tolga' => array(),
4722
- 'torsken' => array(),
4723
- 'tranoy' => array(),
4724
- 'tranøy' => array(),
4725
- 'tromso' => array(),
4726
- 'tromsø' => array(),
4727
- 'tromsa' => array(),
4728
- 'romsa' => array(),
4729
- 'trondheim' => array(),
4730
- 'troandin' => array(),
4731
- 'trysil' => array(),
4732
- 'trana' => array(),
4733
- 'træna' => array(),
4734
- 'trogstad' => array(),
4735
- 'trøgstad' => array(),
4736
- 'tvedestrand' => array(),
4737
- 'tydal' => array(),
4738
- 'tynset' => array(),
4739
- 'tysfjord' => array(),
4740
- 'divtasvuodna' => array(),
4741
- 'divttasvuotna' => array(),
4742
- 'tysnes' => array(),
4743
- 'tysvar' => array(),
4744
- 'tysvær' => array(),
4745
- 'tonsberg' => array(),
4746
- 'tønsberg' => array(),
4747
- 'ullensaker' => array(),
4748
- 'ullensvang' => array(),
4749
- 'ulvik' => array(),
4750
- 'utsira' => array(),
4751
- 'vadso' => array(),
4752
- 'vadsø' => array(),
4753
- 'cahcesuolo' => array(),
4754
- 'čáhcesuolo' => array(),
4755
- 'vaksdal' => array(),
4756
- 'valle' => array(),
4757
- 'vang' => array(),
4758
- 'vanylven' => array(),
4759
- 'vardo' => array(),
4760
- 'vardø' => array(),
4761
- 'varggat' => array(),
4762
- 'várggát' => array(),
4763
- 'vefsn' => array(),
4764
- 'vaapste' => array(),
4765
- 'vega' => array(),
4766
- 'vegarshei' => array(),
4767
- 'vegårshei' => array(),
4768
- 'vennesla' => array(),
4769
- 'verdal' => array(),
4770
- 'verran' => array(),
4771
- 'vestby' => array(),
4772
- 'vestnes' => array(),
4773
- 'vestre-slidre' => array(),
4774
- 'vestre-toten' => array(),
4775
- 'vestvagoy' => array(),
4776
- 'vestvågøy' => array(),
4777
- 'vevelstad' => array(),
4778
- 'vik' => array(),
4779
- 'vikna' => array(),
4780
- 'vindafjord' => array(),
4781
- 'volda' => array(),
4782
- 'voss' => array(),
4783
- 'varoy' => array(),
4784
- 'værøy' => array(),
4785
- 'vagan' => array(),
4786
- 'vågan' => array(),
4787
- 'voagat' => array(),
4788
- 'vagsoy' => array(),
4789
- 'vågsøy' => array(),
4790
- 'vaga' => array(),
4791
- 'vågå' => array(),
4792
- 'ostfold' => array('valer' => array()),
4793
- 'østfold' => array('våler' => array()),
4794
- 'co' => array(),
4795
- 'blogspot' => array()),
4796
- 'np' => array('*' => array()),
4797
- 'nr' => array('biz' => array(),
4798
- 'info' => array(),
4799
- 'gov' => array(),
4800
- 'edu' => array(),
4801
- 'org' => array(),
4802
- 'net' => array(),
4803
- 'com' => array()),
4804
- 'nu' => array('merseine' => array(),
4805
- 'mine' => array(),
4806
- 'shacknet' => array()),
4807
- 'nz' => array('ac' => array(),
4808
- 'co' => array('blogspot' => array()),
4809
- 'cri' => array(),
4810
- 'geek' => array(),
4811
- 'gen' => array(),
4812
- 'govt' => array(),
4813
- 'health' => array(),
4814
- 'iwi' => array(),
4815
- 'kiwi' => array(),
4816
- 'maori' => array(),
4817
- 'mil' => array(),
4818
- 'māori' => array(),
4819
- 'net' => array(),
4820
- 'org' => array(),
4821
- 'parliament' => array(),
4822
- 'school' => array()),
4823
- 'om' => array('co' => array(),
4824
- 'com' => array(),
4825
- 'edu' => array(),
4826
- 'gov' => array(),
4827
- 'med' => array(),
4828
- 'museum' => array(),
4829
- 'net' => array(),
4830
- 'org' => array(),
4831
- 'pro' => array()),
4832
- 'org' => array('ae' => array(),
4833
- 'us' => array(),
4834
- 'dyndns' => array('go' => array(),
4835
- 'home' => array()),
4836
- 'blogdns' => array(),
4837
- 'blogsite' => array(),
4838
- 'boldlygoingnowhere' => array(),
4839
- 'dnsalias' => array(),
4840
- 'dnsdojo' => array(),
4841
- 'doesntexist' => array(),
4842
- 'dontexist' => array(),
4843
- 'doomdns' => array(),
4844
- 'dvrdns' => array(),
4845
- 'dynalias' => array(),
4846
- 'endofinternet' => array(),
4847
- 'endoftheinternet' => array(),
4848
- 'from-me' => array(),
4849
- 'game-host' => array(),
4850
- 'gotdns' => array(),
4851
- 'hobby-site' => array(),
4852
- 'homedns' => array(),
4853
- 'homeftp' => array(),
4854
- 'homelinux' => array(),
4855
- 'homeunix' => array(),
4856
- 'is-a-bruinsfan' => array(),
4857
- 'is-a-candidate' => array(),
4858
- 'is-a-celticsfan' => array(),
4859
- 'is-a-chef' => array(),
4860
- 'is-a-geek' => array(),
4861
- 'is-a-knight' => array(),
4862
- 'is-a-linux-user' => array(),
4863
- 'is-a-patsfan' => array(),
4864
- 'is-a-soxfan' => array(),
4865
- 'is-found' => array(),
4866
- 'is-lost' => array(),
4867
- 'is-saved' => array(),
4868
- 'is-very-bad' => array(),
4869
- 'is-very-evil' => array(),
4870
- 'is-very-good' => array(),
4871
- 'is-very-nice' => array(),
4872
- 'is-very-sweet' => array(),
4873
- 'isa-geek' => array(),
4874
- 'kicks-ass' => array(),
4875
- 'misconfused' => array(),
4876
- 'podzone' => array(),
4877
- 'readmyblog' => array(),
4878
- 'selfip' => array(),
4879
- 'sellsyourhome' => array(),
4880
- 'servebbs' => array(),
4881
- 'serveftp' => array(),
4882
- 'servegame' => array(),
4883
- 'stuff-4-sale' => array(),
4884
- 'webhop' => array(),
4885
- 'za' => array()),
4886
- 'pa' => array('ac' => array(),
4887
- 'gob' => array(),
4888
- 'com' => array(),
4889
- 'org' => array(),
4890
- 'sld' => array(),
4891
- 'edu' => array(),
4892
- 'net' => array(),
4893
- 'ing' => array(),
4894
- 'abo' => array(),
4895
- 'med' => array(),
4896
- 'nom' => array()),
4897
- 'pe' => array('edu' => array(),
4898
- 'gob' => array(),
4899
- 'nom' => array(),
4900
- 'mil' => array(),
4901
- 'org' => array(),
4902
- 'com' => array(),
4903
- 'net' => array()),
4904
- 'pf' => array('com' => array(),
4905
- 'org' => array(),
4906
- 'edu' => array()),
4907
- 'pg' => array('*' => array()),
4908
- 'ph' => array('com' => array(),
4909
- 'net' => array(),
4910
- 'org' => array(),
4911
- 'gov' => array(),
4912
- 'edu' => array(),
4913
- 'ngo' => array(),
4914
- 'mil' => array(),
4915
- 'i' => array()),
4916
- 'pk' => array('com' => array(),
4917
- 'net' => array(),
4918
- 'edu' => array(),
4919
- 'org' => array(),
4920
- 'fam' => array(),
4921
- 'biz' => array(),
4922
- 'web' => array(),
4923
- 'gov' => array(),
4924
- 'gob' => array(),
4925
- 'gok' => array(),
4926
- 'gon' => array(),
4927
- 'gop' => array(),
4928
- 'gos' => array(),
4929
- 'info' => array()),
4930
- 'pl' => array('aid' => array(),
4931
- 'agro' => array(),
4932
- 'atm' => array(),
4933
- 'auto' => array(),
4934
- 'biz' => array(),
4935
- 'com' => array(),
4936
- 'edu' => array(),
4937
- 'gmina' => array(),
4938
- 'gsm' => array(),
4939
- 'info' => array(),
4940
- 'mail' => array(),
4941
- 'miasta' => array(),
4942
- 'media' => array(),
4943
- 'mil' => array(),
4944
- 'net' => array(),
4945
- 'nieruchomosci' => array(),
4946
- 'nom' => array(),
4947
- 'org' => array(),
4948
- 'pc' => array(),
4949
- 'powiat' => array(),
4950
- 'priv' => array(),
4951
- 'realestate' => array(),
4952
- 'rel' => array(),
4953
- 'sex' => array(),
4954
- 'shop' => array(),
4955
- 'sklep' => array(),
4956
- 'sos' => array(),
4957
- 'szkola' => array(),
4958
- 'targi' => array(),
4959
- 'tm' => array(),
4960
- 'tourism' => array(),
4961
- 'travel' => array(),
4962
- 'turystyka' => array(),
4963
- '6bone' => array(),
4964
- 'art' => array(),
4965
- 'mbone' => array(),
4966
- 'gov' => array('uw' => array(),
4967
- 'um' => array(),
4968
- 'ug' => array(),
4969
- 'upow' => array(),
4970
- 'starostwo' => array(),
4971
- 'so' => array(),
4972
- 'sr' => array(),
4973
- 'po' => array(),
4974
- 'pa' => array()),
4975
- 'ngo' => array(),
4976
- 'irc' => array(),
4977
- 'usenet' => array(),
4978
- 'augustow' => array(),
4979
- 'babia-gora' => array(),
4980
- 'bedzin' => array(),
4981
- 'beskidy' => array(),
4982
- 'bialowieza' => array(),
4983
- 'bialystok' => array(),
4984
- 'bielawa' => array(),
4985
- 'bieszczady' => array(),
4986
- 'boleslawiec' => array(),
4987
- 'bydgoszcz' => array(),
4988
- 'bytom' => array(),
4989
- 'cieszyn' => array(),
4990
- 'czeladz' => array(),
4991
- 'czest' => array(),
4992
- 'dlugoleka' => array(),
4993
- 'elblag' => array(),
4994
- 'elk' => array(),
4995
- 'glogow' => array(),
4996
- 'gniezno' => array(),
4997
- 'gorlice' => array(),
4998
- 'grajewo' => array(),
4999
- 'ilawa' => array(),
5000
- 'jaworzno' => array(),
5001
- 'jelenia-gora' => array(),
5002
- 'jgora' => array(),
5003
- 'kalisz' => array(),
5004
- 'kazimierz-dolny' => array(),
5005
- 'karpacz' => array(),
5006
- 'kartuzy' => array(),
5007
- 'kaszuby' => array(),
5008
- 'katowice' => array(),
5009
- 'kepno' => array(),
5010
- 'ketrzyn' => array(),
5011
- 'klodzko' => array(),
5012
- 'kobierzyce' => array(),
5013
- 'kolobrzeg' => array(),
5014
- 'konin' => array(),
5015
- 'konskowola' => array(),
5016
- 'kutno' => array(),
5017
- 'lapy' => array(),
5018
- 'lebork' => array(),
5019
- 'legnica' => array(),
5020
- 'lezajsk' => array(),
5021
- 'limanowa' => array(),
5022
- 'lomza' => array(),
5023
- 'lowicz' => array(),
5024
- 'lubin' => array(),
5025
- 'lukow' => array(),
5026
- 'malbork' => array(),
5027
- 'malopolska' => array(),
5028
- 'mazowsze' => array(),
5029
- 'mazury' => array(),
5030
- 'mielec' => array(),
5031
- 'mielno' => array(),
5032
- 'mragowo' => array(),
5033
- 'naklo' => array(),
5034
- 'nowaruda' => array(),
5035
- 'nysa' => array(),
5036
- 'olawa' => array(),
5037
- 'olecko' => array(),
5038
- 'olkusz' => array(),
5039
- 'olsztyn' => array(),
5040
- 'opoczno' => array(),
5041
- 'opole' => array(),
5042
- 'ostroda' => array(),
5043
- 'ostroleka' => array(),
5044
- 'ostrowiec' => array(),
5045
- 'ostrowwlkp' => array(),
5046
- 'pila' => array(),
5047
- 'pisz' => array(),
5048
- 'podhale' => array(),
5049
- 'podlasie' => array(),
5050
- 'polkowice' => array(),
5051
- 'pomorze' => array(),
5052
- 'pomorskie' => array(),
5053
- 'prochowice' => array(),
5054
- 'pruszkow' => array(),
5055
- 'przeworsk' => array(),
5056
- 'pulawy' => array(),
5057
- 'radom' => array(),
5058
- 'rawa-maz' => array(),
5059
- 'rybnik' => array(),
5060
- 'rzeszow' => array(),
5061
- 'sanok' => array(),
5062
- 'sejny' => array(),
5063
- 'siedlce' => array(),
5064
- 'slask' => array(),
5065
- 'slupsk' => array(),
5066
- 'sosnowiec' => array(),
5067
- 'stalowa-wola' => array(),
5068
- 'skoczow' => array(),
5069
- 'starachowice' => array(),
5070
- 'stargard' => array(),
5071
- 'suwalki' => array(),
5072
- 'swidnica' => array(),
5073
- 'swiebodzin' => array(),
5074
- 'swinoujscie' => array(),
5075
- 'szczecin' => array(),
5076
- 'szczytno' => array(),
5077
- 'tarnobrzeg' => array(),
5078
- 'tgory' => array(),
5079
- 'turek' => array(),
5080
- 'tychy' => array(),
5081
- 'ustka' => array(),
5082
- 'walbrzych' => array(),
5083
- 'warmia' => array(),
5084
- 'warszawa' => array(),
5085
- 'waw' => array(),
5086
- 'wegrow' => array(),
5087
- 'wielun' => array(),
5088
- 'wlocl' => array(),
5089
- 'wloclawek' => array(),
5090
- 'wodzislaw' => array(),
5091
- 'wolomin' => array(),
5092
- 'wroclaw' => array(),
5093
- 'zachpomor' => array(),
5094
- 'zagan' => array(),
5095
- 'zarow' => array(),
5096
- 'zgora' => array(),
5097
- 'zgorzelec' => array(),
5098
- 'gda' => array(),
5099
- 'gdansk' => array(),
5100
- 'gdynia' => array(),
5101
- 'med' => array(),
5102
- 'sopot' => array(),
5103
- 'gliwice' => array(),
5104
- 'krakow' => array(),
5105
- 'poznan' => array(),
5106
- 'wroc' => array(),
5107
- 'zakopane' => array(),
5108
- 'co' => array()),
5109
- 'pm' => array(),
5110
- 'pn' => array('gov' => array(),
5111
- 'co' => array(),
5112
- 'org' => array(),
5113
- 'edu' => array(),
5114
- 'net' => array()),
5115
- 'post' => array(),
5116
- 'pr' => array('com' => array(),
5117
- 'net' => array(),
5118
- 'org' => array(),
5119
- 'gov' => array(),
5120
- 'edu' => array(),
5121
- 'isla' => array(),
5122
- 'pro' => array(),
5123
- 'biz' => array(),
5124
- 'info' => array(),
5125
- 'name' => array(),
5126
- 'est' => array(),
5127
- 'prof' => array(),
5128
- 'ac' => array()),
5129
- 'pro' => array('aca' => array(),
5130
- 'bar' => array(),
5131
- 'cpa' => array(),
5132
- 'jur' => array(),
5133
- 'law' => array(),
5134
- 'med' => array(),
5135
- 'eng' => array()),
5136
- 'ps' => array('edu' => array(),
5137
- 'gov' => array(),
5138
- 'sec' => array(),
5139
- 'plo' => array(),
5140
- 'com' => array(),
5141
- 'org' => array(),
5142
- 'net' => array()),
5143
- 'pt' => array('net' => array(),
5144
- 'gov' => array(),
5145
- 'org' => array(),
5146
- 'edu' => array(),
5147
- 'int' => array(),
5148
- 'publ' => array(),
5149
- 'com' => array(),
5150
- 'nome' => array(),
5151
- 'blogspot' => array()),
5152
- 'pw' => array('co' => array(),
5153
- 'ne' => array(),
5154
- 'or' => array(),
5155
- 'ed' => array(),
5156
- 'go' => array(),
5157
- 'belau' => array()),
5158
- 'py' => array('com' => array(),
5159
- 'coop' => array(),
5160
- 'edu' => array(),
5161
- 'gov' => array(),
5162
- 'mil' => array(),
5163
- 'net' => array(),
5164
- 'org' => array()),
5165
- 'qa' => array('com' => array(),
5166
- 'edu' => array(),
5167
- 'gov' => array(),
5168
- 'mil' => array(),
5169
- 'name' => array(),
5170
- 'net' => array(),
5171
- 'org' => array(),
5172
- 'sch' => array()),
5173
- 're' => array('com' => array(),
5174
- 'asso' => array(),
5175
- 'nom' => array(),
5176
- 'blogspot' => array()),
5177
- 'ro' => array('com' => array(),
5178
- 'org' => array(),
5179
- 'tm' => array(),
5180
- 'nt' => array(),
5181
- 'nom' => array(),
5182
- 'info' => array(),
5183
- 'rec' => array(),
5184
- 'arts' => array(),
5185
- 'firm' => array(),
5186
- 'store' => array(),
5187
- 'www' => array(),
5188
- 'blogspot' => array()),
5189
- 'rs' => array('co' => array(),
5190
- 'org' => array(),
5191
- 'edu' => array(),
5192
- 'ac' => array(),
5193
- 'gov' => array(),
5194
- 'in' => array()),
5195
- 'ru' => array('ac' => array(),
5196
- 'com' => array(),
5197
- 'edu' => array(),
5198
- 'int' => array(),
5199
- 'net' => array(),
5200
- 'org' => array(),
5201
- 'pp' => array(),
5202
- 'adygeya' => array(),
5203
- 'altai' => array(),
5204
- 'amur' => array(),
5205
- 'arkhangelsk' => array(),
5206
- 'astrakhan' => array(),
5207
- 'bashkiria' => array(),
5208
- 'belgorod' => array(),
5209
- 'bir' => array(),
5210
- 'bryansk' => array(),
5211
- 'buryatia' => array(),
5212
- 'cbg' => array(),
5213
- 'chel' => array(),
5214
- 'chelyabinsk' => array(),
5215
- 'chita' => array(),
5216
- 'chukotka' => array(),
5217
- 'chuvashia' => array(),
5218
- 'dagestan' => array(),
5219
- 'dudinka' => array(),
5220
- 'e-burg' => array(),
5221
- 'grozny' => array(),
5222
- 'irkutsk' => array(),
5223
- 'ivanovo' => array(),
5224
- 'izhevsk' => array(),
5225
- 'jar' => array(),
5226
- 'joshkar-ola' => array(),
5227
- 'kalmykia' => array(),
5228
- 'kaluga' => array(),
5229
- 'kamchatka' => array(),
5230
- 'karelia' => array(),
5231
- 'kazan' => array(),
5232
- 'kchr' => array(),
5233
- 'kemerovo' => array(),
5234
- 'khabarovsk' => array(),
5235
- 'khakassia' => array(),
5236
- 'khv' => array(),
5237
- 'kirov' => array(),
5238
- 'koenig' => array(),
5239
- 'komi' => array(),
5240
- 'kostroma' => array(),
5241
- 'krasnoyarsk' => array(),
5242
- 'kuban' => array(),
5243
- 'kurgan' => array(),
5244
- 'kursk' => array(),
5245
- 'lipetsk' => array(),
5246
- 'magadan' => array(),
5247
- 'mari' => array(),
5248
- 'mari-el' => array(),
5249
- 'marine' => array(),
5250
- 'mordovia' => array(),
5251
- 'mosreg' => array(),
5252
- 'msk' => array(),
5253
- 'murmansk' => array(),
5254
- 'nalchik' => array(),
5255
- 'nnov' => array(),
5256
- 'nov' => array(),
5257
- 'novosibirsk' => array(),
5258
- 'nsk' => array(),
5259
- 'omsk' => array(),
5260
- 'orenburg' => array(),
5261
- 'oryol' => array(),
5262
- 'palana' => array(),
5263
- 'penza' => array(),
5264
- 'perm' => array(),
5265
- 'ptz' => array(),
5266
- 'rnd' => array(),
5267
- 'ryazan' => array(),
5268
- 'sakhalin' => array(),
5269
- 'samara' => array(),
5270
- 'saratov' => array(),
5271
- 'simbirsk' => array(),
5272
- 'smolensk' => array(),
5273
- 'spb' => array(),
5274
- 'stavropol' => array(),
5275
- 'stv' => array(),
5276
- 'surgut' => array(),
5277
- 'tambov' => array(),
5278
- 'tatarstan' => array(),
5279
- 'tom' => array(),
5280
- 'tomsk' => array(),
5281
- 'tsaritsyn' => array(),
5282
- 'tsk' => array(),
5283
- 'tula' => array(),
5284
- 'tuva' => array(),
5285
- 'tver' => array(),
5286
- 'tyumen' => array(),
5287
- 'udm' => array(),
5288
- 'udmurtia' => array(),
5289
- 'ulan-ude' => array(),
5290
- 'vladikavkaz' => array(),
5291
- 'vladimir' => array(),
5292
- 'vladivostok' => array(),
5293
- 'volgograd' => array(),
5294
- 'vologda' => array(),
5295
- 'voronezh' => array(),
5296
- 'vrn' => array(),
5297
- 'vyatka' => array(),
5298
- 'yakutia' => array(),
5299
- 'yamal' => array(),
5300
- 'yaroslavl' => array(),
5301
- 'yekaterinburg' => array(),
5302
- 'yuzhno-sakhalinsk' => array(),
5303
- 'amursk' => array(),
5304
- 'baikal' => array(),
5305
- 'cmw' => array(),
5306
- 'fareast' => array(),
5307
- 'jamal' => array(),
5308
- 'kms' => array(),
5309
- 'k-uralsk' => array(),
5310
- 'kustanai' => array(),
5311
- 'kuzbass' => array(),
5312
- 'magnitka' => array(),
5313
- 'mytis' => array(),
5314
- 'nakhodka' => array(),
5315
- 'nkz' => array(),
5316
- 'norilsk' => array(),
5317
- 'oskol' => array(),
5318
- 'pyatigorsk' => array(),
5319
- 'rubtsovsk' => array(),
5320
- 'snz' => array(),
5321
- 'syzran' => array(),
5322
- 'vdonsk' => array(),
5323
- 'zgrad' => array(),
5324
- 'gov' => array(),
5325
- 'mil' => array(),
5326
- 'test' => array()),
5327
- 'rw' => array('gov' => array(),
5328
- 'net' => array(),
5329
- 'edu' => array(),
5330
- 'ac' => array(),
5331
- 'com' => array(),
5332
- 'co' => array(),
5333
- 'int' => array(),
5334
- 'mil' => array(),
5335
- 'gouv' => array()),
5336
- 'sa' => array('com' => array(),
5337
- 'net' => array(),
5338
- 'org' => array(),
5339
- 'gov' => array(),
5340
- 'med' => array(),
5341
- 'pub' => array(),
5342
- 'edu' => array(),
5343
- 'sch' => array()),
5344
- 'sb' => array('com' => array(),
5345
- 'edu' => array(),
5346
- 'gov' => array(),
5347
- 'net' => array(),
5348
- 'org' => array()),
5349
- 'sc' => array('com' => array(),
5350
- 'gov' => array(),
5351
- 'net' => array(),
5352
- 'org' => array(),
5353
- 'edu' => array()),
5354
- 'sd' => array('com' => array(),
5355
- 'net' => array(),
5356
- 'org' => array(),
5357
- 'edu' => array(),
5358
- 'med' => array(),
5359
- 'tv' => array(),
5360
- 'gov' => array(),
5361
- 'info' => array()),
5362
- 'se' => array('a' => array(),
5363
- 'ac' => array(),
5364
- 'b' => array(),
5365
- 'bd' => array(),
5366
- 'brand' => array(),
5367
- 'c' => array(),
5368
- 'd' => array(),
5369
- 'e' => array(),
5370
- 'f' => array(),
5371
- 'fh' => array(),
5372
- 'fhsk' => array(),
5373
- 'fhv' => array(),
5374
- 'g' => array(),
5375
- 'h' => array(),
5376
- 'i' => array(),
5377
- 'k' => array(),
5378
- 'komforb' => array(),
5379
- 'kommunalforbund' => array(),
5380
- 'komvux' => array(),
5381
- 'l' => array(),
5382
- 'lanbib' => array(),
5383
- 'm' => array(),
5384
- 'n' => array(),
5385
- 'naturbruksgymn' => array(),
5386
- 'o' => array(),
5387
- 'org' => array(),
5388
- 'p' => array(),
5389
- 'parti' => array(),
5390
- 'pp' => array(),
5391
- 'press' => array(),
5392
- 'r' => array(),
5393
- 's' => array(),
5394
- 't' => array(),
5395
- 'tm' => array(),
5396
- 'u' => array(),
5397
- 'w' => array(),
5398
- 'x' => array(),
5399
- 'y' => array(),
5400
- 'z' => array(),
5401
- 'com' => array(),
5402
- 'blogspot' => array()),
5403
- 'sg' => array('com' => array(),
5404
- 'net' => array(),
5405
- 'org' => array(),
5406
- 'gov' => array(),
5407
- 'edu' => array(),
5408
- 'per' => array(),
5409
- 'blogspot' => array()),
5410
- 'sh' => array('com' => array(),
5411
- 'net' => array(),
5412
- 'gov' => array(),
5413
- 'org' => array(),
5414
- 'mil' => array()),
5415
- 'si' => array(),
5416
- 'sj' => array(),
5417
- 'sk' => array('blogspot' => array()),
5418
- 'sl' => array('com' => array(),
5419
- 'net' => array(),
5420
- 'edu' => array(),
5421
- 'gov' => array(),
5422
- 'org' => array()),
5423
- 'sm' => array(),
5424
- 'sn' => array('art' => array(),
5425
- 'com' => array(),
5426
- 'edu' => array(),
5427
- 'gouv' => array(),
5428
- 'org' => array(),
5429
- 'perso' => array(),
5430
- 'univ' => array()),
5431
- 'so' => array('com' => array(),
5432
- 'net' => array(),
5433
- 'org' => array()),
5434
- 'sr' => array(),
5435
- 'st' => array('co' => array(),
5436
- 'com' => array(),
5437
- 'consulado' => array(),
5438
- 'edu' => array(),
5439
- 'embaixada' => array(),
5440
- 'gov' => array(),
5441
- 'mil' => array(),
5442
- 'net' => array(),
5443
- 'org' => array(),
5444
- 'principe' => array(),
5445
- 'saotome' => array(),
5446
- 'store' => array()),
5447
- 'su' => array(),
5448
- 'sv' => array('com' => array(),
5449
- 'edu' => array(),
5450
- 'gob' => array(),
5451
- 'org' => array(),
5452
- 'red' => array()),
5453
- 'sx' => array('gov' => array()),
5454
- 'sy' => array('edu' => array(),
5455
- 'gov' => array(),
5456
- 'net' => array(),
5457
- 'mil' => array(),
5458
- 'com' => array(),
5459
- 'org' => array()),
5460
- 'sz' => array('co' => array(),
5461
- 'ac' => array(),
5462
- 'org' => array()),
5463
- 'tc' => array(),
5464
- 'td' => array('blogspot' => array()),
5465
- 'tel' => array(),
5466
- 'tf' => array(),
5467
- 'tg' => array(),
5468
- 'th' => array('ac' => array(),
5469
- 'co' => array(),
5470
- 'go' => array(),
5471
- 'in' => array(),
5472
- 'mi' => array(),
5473
- 'net' => array(),
5474
- 'or' => array()),
5475
- 'tj' => array('ac' => array(),
5476
- 'biz' => array(),
5477
- 'co' => array(),
5478
- 'com' => array(),
5479
- 'edu' => array(),
5480
- 'go' => array(),
5481
- 'gov' => array(),
5482
- 'int' => array(),
5483
- 'mil' => array(),
5484
- 'name' => array(),
5485
- 'net' => array(),
5486
- 'nic' => array(),
5487
- 'org' => array(),
5488
- 'test' => array(),
5489
- 'web' => array()),
5490
- 'tk' => array(),
5491
- 'tl' => array('gov' => array()),
5492
- 'tm' => array('com' => array(),
5493
- 'co' => array(),
5494
- 'org' => array(),
5495
- 'net' => array(),
5496
- 'nom' => array(),
5497
- 'gov' => array(),
5498
- 'mil' => array(),
5499
- 'edu' => array()),
5500
- 'tn' => array('com' => array(),
5501
- 'ens' => array(),
5502
- 'fin' => array(),
5503
- 'gov' => array(),
5504
- 'ind' => array(),
5505
- 'intl' => array(),
5506
- 'nat' => array(),
5507
- 'net' => array(),
5508
- 'org' => array(),
5509
- 'info' => array(),
5510
- 'perso' => array(),
5511
- 'tourism' => array(),
5512
- 'edunet' => array(),
5513
- 'rnrt' => array(),
5514
- 'rns' => array(),
5515
- 'rnu' => array(),
5516
- 'mincom' => array(),
5517
- 'agrinet' => array(),
5518
- 'defense' => array(),
5519
- 'turen' => array()),
5520
- 'to' => array('com' => array(),
5521
- 'gov' => array(),
5522
- 'net' => array(),
5523
- 'org' => array(),
5524
- 'edu' => array(),
5525
- 'mil' => array()),
5526
- 'tp' => array(),
5527
- 'tr' => array('com' => array(),
5528
- 'info' => array(),
5529
- 'biz' => array(),
5530
- 'net' => array(),
5531
- 'org' => array(),
5532
- 'web' => array(),
5533
- 'gen' => array(),
5534
- 'tv' => array(),
5535
- 'av' => array(),
5536
- 'dr' => array(),
5537
- 'bbs' => array(),
5538
- 'name' => array(),
5539
- 'tel' => array(),
5540
- 'gov' => array(),
5541
- 'bel' => array(),
5542
- 'pol' => array(),
5543
- 'mil' => array(),
5544
- 'k12' => array(),
5545
- 'edu' => array(),
5546
- 'kep' => array(),
5547
- 'nc' => array('gov' => array())),
5548
- 'travel' => array(),
5549
- 'tt' => array('co' => array(),
5550
- 'com' => array(),
5551
- 'org' => array(),
5552
- 'net' => array(),
5553
- 'biz' => array(),
5554
- 'info' => array(),
5555
- 'pro' => array(),
5556
- 'int' => array(),
5557
- 'coop' => array(),
5558
- 'jobs' => array(),
5559
- 'mobi' => array(),
5560
- 'travel' => array(),
5561
- 'museum' => array(),
5562
- 'aero' => array(),
5563
- 'name' => array(),
5564
- 'gov' => array(),
5565
- 'edu' => array()),
5566
- 'tv' => array('dyndns' => array(),
5567
- 'better-than' => array(),
5568
- 'on-the-web' => array(),
5569
- 'worse-than' => array()),
5570
- 'tw' => array('edu' => array(),
5571
- 'gov' => array(),
5572
- 'mil' => array(),
5573
- 'com' => array(),
5574
- 'net' => array(),
5575
- 'org' => array(),
5576
- 'idv' => array(),
5577
- 'game' => array(),
5578
- 'ebiz' => array(),
5579
- 'club' => array(),
5580
- '網路' => array(),
5581
- '組織' => array(),
5582
- '商業' => array(),
5583
- 'blogspot' => array()),
5584
- 'tz' => array('ac' => array(),
5585
- 'co' => array(),
5586
- 'go' => array(),
5587
- 'hotel' => array(),
5588
- 'info' => array(),
5589
- 'me' => array(),
5590
- 'mil' => array(),
5591
- 'mobi' => array(),
5592
- 'ne' => array(),
5593
- 'or' => array(),
5594
- 'sc' => array(),
5595
- 'tv' => array()),
5596
- 'ua' => array('com' => array(),
5597
- 'edu' => array(),
5598
- 'gov' => array(),
5599
- 'in' => array(),
5600
- 'net' => array(),
5601
- 'org' => array(),
5602
- 'cherkassy' => array(),
5603
- 'cherkasy' => array(),
5604
- 'chernigov' => array(),
5605
- 'chernihiv' => array(),
5606
- 'chernivtsi' => array(),
5607
- 'chernovtsy' => array(),
5608
- 'ck' => array(),
5609
- 'cn' => array(),
5610
- 'cr' => array(),
5611
- 'crimea' => array(),
5612
- 'cv' => array(),
5613
- 'dn' => array(),
5614
- 'dnepropetrovsk' => array(),
5615
- 'dnipropetrovsk' => array(),
5616
- 'dominic' => array(),
5617
- 'donetsk' => array(),
5618
- 'dp' => array(),
5619
- 'if' => array(),
5620
- 'ivano-frankivsk' => array(),
5621
- 'kh' => array(),
5622
- 'kharkiv' => array(),
5623
- 'kharkov' => array(),
5624
- 'kherson' => array(),
5625
- 'khmelnitskiy' => array(),
5626
- 'khmelnytskyi' => array(),
5627
- 'kiev' => array(),
5628
- 'kirovograd' => array(),
5629
- 'km' => array(),
5630
- 'kr' => array(),
5631
- 'krym' => array(),
5632
- 'ks' => array(),
5633
- 'kv' => array(),
5634
- 'kyiv' => array(),
5635
- 'lg' => array(),
5636
- 'lt' => array(),
5637
- 'lugansk' => array(),
5638
- 'lutsk' => array(),
5639
- 'lv' => array(),
5640
- 'lviv' => array(),
5641
- 'mk' => array(),
5642
- 'mykolaiv' => array(),
5643
- 'nikolaev' => array(),
5644
- 'od' => array(),
5645
- 'odesa' => array(),
5646
- 'odessa' => array(),
5647
- 'pl' => array(),
5648
- 'poltava' => array(),
5649
- 'rivne' => array(),
5650
- 'rovno' => array(),
5651
- 'rv' => array(),
5652
- 'sb' => array(),
5653
- 'sebastopol' => array(),
5654
- 'sevastopol' => array(),
5655
- 'sm' => array(),
5656
- 'sumy' => array(),
5657
- 'te' => array(),
5658
- 'ternopil' => array(),
5659
- 'uz' => array(),
5660
- 'uzhgorod' => array(),
5661
- 'vinnica' => array(),
5662
- 'vinnytsia' => array(),
5663
- 'vn' => array(),
5664
- 'volyn' => array(),
5665
- 'yalta' => array(),
5666
- 'zaporizhzhe' => array(),
5667
- 'zaporizhzhia' => array(),
5668
- 'zhitomir' => array(),
5669
- 'zhytomyr' => array(),
5670
- 'zp' => array(),
5671
- 'zt' => array(),
5672
- 'co' => array(),
5673
- 'pp' => array()),
5674
- 'ug' => array('co' => array(),
5675
- 'or' => array(),
5676
- 'ac' => array(),
5677
- 'sc' => array(),
5678
- 'go' => array(),
5679
- 'ne' => array(),
5680
- 'com' => array(),
5681
- 'org' => array()),
5682
- 'uk' => array('ac' => array(),
5683
- 'co' => array('blogspot' => array()),
5684
- 'gov' => array('service' => array()),
5685
- 'ltd' => array(),
5686
- 'me' => array(),
5687
- 'net' => array(),
5688
- 'nhs' => array(),
5689
- 'org' => array(),
5690
- 'plc' => array(),
5691
- 'police' => array(),
5692
- 'sch' => array('*' => array())),
5693
- 'us' => array('dni' => array(),
5694
- 'fed' => array(),
5695
- 'isa' => array(),
5696
- 'kids' => array(),
5697
- 'nsn' => array(),
5698
- 'ak' => array('k12' => array(),
5699
- 'cc' => array(),
5700
- 'lib' => array()),
5701
- 'al' => array('k12' => array(),
5702
- 'cc' => array(),
5703
- 'lib' => array()),
5704
- 'ar' => array('k12' => array(),
5705
- 'cc' => array(),
5706
- 'lib' => array()),
5707
- 'as' => array('k12' => array(),
5708
- 'cc' => array(),
5709
- 'lib' => array()),
5710
- 'az' => array('k12' => array(),
5711
- 'cc' => array(),
5712
- 'lib' => array()),
5713
- 'ca' => array('k12' => array(),
5714
- 'cc' => array(),
5715
- 'lib' => array()),
5716
- 'co' => array('k12' => array(),
5717
- 'cc' => array(),
5718
- 'lib' => array()),
5719
- 'ct' => array('k12' => array(),
5720
- 'cc' => array(),
5721
- 'lib' => array()),
5722
- 'dc' => array('k12' => array(),
5723
- 'cc' => array(),
5724
- 'lib' => array()),
5725
- 'de' => array('k12' => array(),
5726
- 'cc' => array(),
5727
- 'lib' => array()),
5728
- 'fl' => array('k12' => array(),
5729
- 'cc' => array(),
5730
- 'lib' => array()),
5731
- 'ga' => array('k12' => array(),
5732
- 'cc' => array(),
5733
- 'lib' => array()),
5734
- 'gu' => array('k12' => array(),
5735
- 'cc' => array(),
5736
- 'lib' => array()),
5737
- 'hi' => array('cc' => array(),
5738
- 'lib' => array()),
5739
- 'ia' => array('k12' => array(),
5740
- 'cc' => array(),
5741
- 'lib' => array()),
5742
- 'id' => array('k12' => array(),
5743
- 'cc' => array(),
5744
- 'lib' => array()),
5745
- 'il' => array('k12' => array(),
5746
- 'cc' => array(),
5747
- 'lib' => array()),
5748
- 'in' => array('k12' => array(),
5749
- 'cc' => array(),
5750
- 'lib' => array()),
5751
- 'ks' => array('k12' => array(),
5752
- 'cc' => array(),
5753
- 'lib' => array()),
5754
- 'ky' => array('k12' => array(),
5755
- 'cc' => array(),
5756
- 'lib' => array()),
5757
- 'la' => array('k12' => array(),
5758
- 'cc' => array(),
5759
- 'lib' => array()),
5760
- 'ma' => array('k12' => array('pvt' => array(),
5761
- 'chtr' => array(),
5762
- 'paroch' => array()),
5763
- 'cc' => array(),
5764
- 'lib' => array()),
5765
- 'md' => array('k12' => array(),
5766
- 'cc' => array(),
5767
- 'lib' => array()),
5768
- 'me' => array('k12' => array(),
5769
- 'cc' => array(),
5770
- 'lib' => array()),
5771
- 'mi' => array('k12' => array(),
5772
- 'cc' => array(),
5773
- 'lib' => array()),
5774
- 'mn' => array('k12' => array(),
5775
- 'cc' => array(),
5776
- 'lib' => array()),
5777
- 'mo' => array('k12' => array(),
5778
- 'cc' => array(),
5779
- 'lib' => array()),
5780
- 'ms' => array('k12' => array(),
5781
- 'cc' => array(),
5782
- 'lib' => array()),
5783
- 'mt' => array('k12' => array(),
5784
- 'cc' => array(),
5785
- 'lib' => array()),
5786
- 'nc' => array('k12' => array(),
5787
- 'cc' => array(),
5788
- 'lib' => array()),
5789
- 'nd' => array('cc' => array(),
5790
- 'lib' => array()),
5791
- 'ne' => array('k12' => array(),
5792
- 'cc' => array(),
5793
- 'lib' => array()),
5794
- 'nh' => array('k12' => array(),
5795
- 'cc' => array(),
5796
- 'lib' => array()),
5797
- 'nj' => array('k12' => array(),
5798
- 'cc' => array(),
5799
- 'lib' => array()),
5800
- 'nm' => array('k12' => array(),
5801
- 'cc' => array(),
5802
- 'lib' => array()),
5803
- 'nv' => array('k12' => array(),
5804
- 'cc' => array(),
5805
- 'lib' => array()),
5806
- 'ny' => array('k12' => array(),
5807
- 'cc' => array(),
5808
- 'lib' => array()),
5809
- 'oh' => array('k12' => array(),
5810
- 'cc' => array(),
5811
- 'lib' => array()),
5812
- 'ok' => array('k12' => array(),
5813
- 'cc' => array(),
5814
- 'lib' => array()),
5815
- 'or' => array('k12' => array(),
5816
- 'cc' => array(),
5817
- 'lib' => array()),
5818
- 'pa' => array('k12' => array(),
5819
- 'cc' => array(),
5820
- 'lib' => array()),
5821
- 'pr' => array('k12' => array(),
5822
- 'cc' => array(),
5823
- 'lib' => array()),
5824
- 'ri' => array('k12' => array(),
5825
- 'cc' => array(),
5826
- 'lib' => array()),
5827
- 'sc' => array('k12' => array(),
5828
- 'cc' => array(),
5829
- 'lib' => array()),
5830
- 'sd' => array('cc' => array(),
5831
- 'lib' => array()),
5832
- 'tn' => array('k12' => array(),
5833
- 'cc' => array(),
5834
- 'lib' => array()),
5835
- 'tx' => array('k12' => array(),
5836
- 'cc' => array(),
5837
- 'lib' => array()),
5838
- 'ut' => array('k12' => array(),
5839
- 'cc' => array(),
5840
- 'lib' => array()),
5841
- 'vi' => array('k12' => array(),
5842
- 'cc' => array(),
5843
- 'lib' => array()),
5844
- 'vt' => array('k12' => array(),
5845
- 'cc' => array(),
5846
- 'lib' => array()),
5847
- 'va' => array('k12' => array(),
5848
- 'cc' => array(),
5849
- 'lib' => array()),
5850
- 'wa' => array('k12' => array(),
5851
- 'cc' => array(),
5852
- 'lib' => array()),
5853
- 'wi' => array('k12' => array(),
5854
- 'cc' => array(),
5855
- 'lib' => array()),
5856
- 'wv' => array('cc' => array()),
5857
- 'wy' => array('k12' => array(),
5858
- 'cc' => array(),
5859
- 'lib' => array()),
5860
- 'is-by' => array(),
5861
- 'land-4-sale' => array(),
5862
- 'stuff-4-sale' => array()),
5863
- 'uy' => array('com' => array(),
5864
- 'edu' => array(),
5865
- 'gub' => array(),
5866
- 'mil' => array(),
5867
- 'net' => array(),
5868
- 'org' => array()),
5869
- 'uz' => array('co' => array(),
5870
- 'com' => array(),
5871
- 'net' => array(),
5872
- 'org' => array()),
5873
- 'va' => array(),
5874
- 'vc' => array('com' => array(),
5875
- 'net' => array(),
5876
- 'org' => array(),
5877
- 'gov' => array(),
5878
- 'mil' => array(),
5879
- 'edu' => array()),
5880
- 've' => array('arts' => array(),
5881
- 'co' => array(),
5882
- 'com' => array(),
5883
- 'e12' => array(),
5884
- 'edu' => array(),
5885
- 'firm' => array(),
5886
- 'gob' => array(),
5887
- 'gov' => array(),
5888
- 'info' => array(),
5889
- 'int' => array(),
5890
- 'mil' => array(),
5891
- 'net' => array(),
5892
- 'org' => array(),
5893
- 'rec' => array(),
5894
- 'store' => array(),
5895
- 'tec' => array(),
5896
- 'web' => array()),
5897
- 'vg' => array(),
5898
- 'vi' => array('co' => array(),
5899
- 'com' => array(),
5900
- 'k12' => array(),
5901
- 'net' => array(),
5902
- 'org' => array()),
5903
- 'vn' => array('com' => array(),
5904
- 'net' => array(),
5905
- 'org' => array(),
5906
- 'edu' => array(),
5907
- 'gov' => array(),
5908
- 'int' => array(),
5909
- 'ac' => array(),
5910
- 'biz' => array(),
5911
- 'info' => array(),
5912
- 'name' => array(),
5913
- 'pro' => array(),
5914
- 'health' => array()),
5915
- 'vu' => array('com' => array(),
5916
- 'edu' => array(),
5917
- 'net' => array(),
5918
- 'org' => array()),
5919
- 'wf' => array(),
5920
- 'ws' => array('com' => array(),
5921
- 'net' => array(),
5922
- 'org' => array(),
5923
- 'gov' => array(),
5924
- 'edu' => array(),
5925
- 'dyndns' => array(),
5926
- 'mypets' => array()),
5927
- 'yt' => array(),
5928
- 'امارات' => array(),
5929
- 'বাংলা' => array(),
5930
- '中国' => array(),
5931
- '中國' => array(),
5932
- 'الجزائر' => array(),
5933
- 'مصر' => array(),
5934
- 'გე' => array(),
5935
- '香港' => array(),
5936
- 'भारत' => array(),
5937
- 'بھارت' => array(),
5938
- 'భారత్' => array(),
5939
- 'ભારત' => array(),
5940
- 'ਭਾਰਤ' => array(),
5941
- 'ভারত' => array(),
5942
- 'இந்தியா' => array(),
5943
- 'ایران' => array(),
5944
- 'ايران' => array(),
5945
- 'الاردن' => array(),
5946
- '한국' => array(),
5947
- 'қаз' => array(),
5948
- 'ලංකා' => array(),
5949
- 'இலங்கை' => array(),
5950
- 'المغرب' => array(),
5951
- 'мон' => array(),
5952
- 'مليسيا' => array(),
5953
- 'عمان' => array(),
5954
- 'فلسطين' => array(),
5955
- 'срб' => array('пр' => array(),
5956
- 'орг' => array(),
5957
- 'обр' => array(),
5958
- 'од' => array(),
5959
- 'упр' => array(),
5960
- 'ак' => array()),
5961
- 'рф' => array(),
5962
- 'قطر' => array(),
5963
- 'السعودية' => array(),
5964
- 'السعودیة' => array(),
5965
- 'السعودیۃ' => array(),
5966
- 'السعوديه' => array(),
5967
- 'سورية' => array(),
5968
- 'سوريا' => array(),
5969
- '新加坡' => array(),
5970
- 'சிங்கப்பூர்' => array(),
5971
- 'ไทย' => array(),
5972
- 'تونس' => array(),
5973
- '台灣' => array(),
5974
- '台湾' => array(),
5975
- '臺灣' => array(),
5976
- 'укр' => array(),
5977
- 'اليمن' => array(),
5978
- 'xxx' => array(),
5979
- 'ye' => array('*' => array()),
5980
- 'za' => array('*' => array()),
5981
- 'zm' => array('*' => array()),
5982
- 'zw' => array('*' => array()),
5983
- 'abbott' => array(),
5984
- 'abogado' => array(),
5985
- 'academy' => array(),
5986
- 'accenture' => array(),
5987
- 'accountants' => array(),
5988
- 'active' => array(),
5989
- 'actor' => array(),
5990
- 'africa' => array(),
5991
- 'agency' => array(),
5992
- 'airforce' => array(),
5993
- 'allfinanz' => array(),
5994
- 'alsace' => array(),
5995
- 'amsterdam' => array(),
5996
- 'android' => array(),
5997
- 'aquarelle' => array(),
5998
- 'archi' => array(),
5999
- 'army' => array(),
6000
- 'associates' => array(),
6001
- 'attorney' => array(),
6002
- 'auction' => array(),
6003
- 'audio' => array(),
6004
- 'autos' => array(),
6005
- 'axa' => array(),
6006
- 'band' => array(),
6007
- 'bar' => array(),
6008
- 'barcelona' => array(),
6009
- 'bargains' => array(),
6010
- 'bauhaus' => array(),
6011
- 'bayern' => array(),
6012
- 'bcn' => array(),
6013
- 'beer' => array(),
6014
- 'berlin' => array(),
6015
- 'best' => array(),
6016
- 'bharti' => array(),
6017
- 'bible' => array(),
6018
- 'bid' => array(),
6019
- 'bike' => array(),
6020
- 'bio' => array(),
6021
- 'black' => array(),
6022
- 'blackfriday' => array(),
6023
- 'bloomberg' => array(),
6024
- 'blue' => array(),
6025
- 'bmw' => array(),
6026
- 'bnl' => array(),
6027
- 'bnpparibas' => array(),
6028
- 'bond' => array(),
6029
- 'boo' => array(),
6030
- 'boutique' => array(),
6031
- 'brussels' => array(),
6032
- 'budapest' => array(),
6033
- 'build' => array(),
6034
- 'builders' => array(),
6035
- 'business' => array(),
6036
- 'buzz' => array(),
6037
- 'bzh' => array(),
6038
- 'cab' => array(),
6039
- 'cal' => array(),
6040
- 'camera' => array(),
6041
- 'camp' => array(),
6042
- 'cancerresearch' => array(),
6043
- 'capetown' => array(),
6044
- 'capital' => array(),
6045
- 'caravan' => array(),
6046
- 'cards' => array(),
6047
- 'care' => array(),
6048
- 'career' => array(),
6049
- 'careers' => array(),
6050
- 'cartier' => array(),
6051
- 'casa' => array(),
6052
- 'cash' => array(),
6053
- 'catering' => array(),
6054
- 'cba' => array(),
6055
- 'cbn' => array(),
6056
- 'center' => array(),
6057
- 'ceo' => array(),
6058
- 'cern' => array(),
6059
- 'cfa' => array(),
6060
- 'channel' => array(),
6061
- 'cheap' => array(),
6062
- 'christmas' => array(),
6063
- 'chrome' => array(),
6064
- 'church' => array(),
6065
- 'citic' => array(),
6066
- 'city' => array(),
6067
- 'claims' => array(),
6068
- 'cleaning' => array(),
6069
- 'click' => array(),
6070
- 'clinic' => array(),
6071
- 'clothing' => array(),
6072
- 'club' => array(),
6073
- 'codes' => array(),
6074
- 'coffee' => array(),
6075
- 'college' => array(),
6076
- 'cologne' => array(),
6077
- 'commbank' => array(),
6078
- 'community' => array(),
6079
- 'company' => array(),
6080
- 'computer' => array(),
6081
- 'condos' => array(),
6082
- 'construction' => array(),
6083
- 'consulting' => array(),
6084
- 'contractors' => array(),
6085
- 'cooking' => array(),
6086
- 'cool' => array(),
6087
- 'country' => array(),
6088
- 'credit' => array(),
6089
- 'creditcard' => array(),
6090
- 'crs' => array(),
6091
- 'cruises' => array(),
6092
- 'cuisinella' => array(),
6093
- 'cymru' => array(),
6094
- 'dabur' => array(),
6095
- 'dad' => array(),
6096
- 'dance' => array(),
6097
- 'dating' => array(),
6098
- 'datsun' => array(),
6099
- 'day' => array(),
6100
- 'deals' => array(),
6101
- 'degree' => array(),
6102
- 'democrat' => array(),
6103
- 'dental' => array(),
6104
- 'dentist' => array(),
6105
- 'desi' => array(),
6106
- 'diamonds' => array(),
6107
- 'diet' => array(),
6108
- 'digital' => array(),
6109
- 'direct' => array(),
6110
- 'directory' => array(),
6111
- 'discount' => array(),
6112
- 'dnp' => array(),
6113
- 'domains' => array(),
6114
- 'doosan' => array(),
6115
- 'durban' => array(),
6116
- 'dvag' => array(),
6117
- 'eat' => array(),
6118
- 'education' => array(),
6119
- 'email' => array(),
6120
- 'emerck' => array(),
6121
- 'engineer' => array(),
6122
- 'engineering' => array(),
6123
- 'enterprises' => array(),
6124
- 'equipment' => array(),
6125
- 'erni' => array(),
6126
- 'esq' => array(),
6127
- 'estate' => array(),
6128
- 'eurovision' => array(),
6129
- 'eus' => array(),
6130
- 'events' => array(),
6131
- 'everbank' => array(),
6132
- 'exchange' => array(),
6133
- 'expert' => array(),
6134
- 'exposed' => array(),
6135
- 'fail' => array(),
6136
- 'fan' => array(),
6137
- 'farm' => array(),
6138
- 'fashion' => array(),
6139
- 'feedback' => array(),
6140
- 'finance' => array(),
6141
- 'financial' => array(),
6142
- 'firmdale' => array(),
6143
- 'fish' => array(),
6144
- 'fishing' => array(),
6145
- 'fitness' => array(),
6146
- 'flights' => array(),
6147
- 'florist' => array(),
6148
- 'flsmidth' => array(),
6149
- 'fly' => array(),
6150
- 'foo' => array(),
6151
- 'forsale' => array(),
6152
- 'foundation' => array(),
6153
- 'frl' => array(),
6154
- 'frogans' => array(),
6155
- 'fund' => array(),
6156
- 'furniture' => array(),
6157
- 'futbol' => array(),
6158
- 'gal' => array(),
6159
- 'gallery' => array(),
6160
- 'garden' => array(),
6161
- 'gbiz' => array(),
6162
- 'gdn' => array(),
6163
- 'gent' => array(),
6164
- 'ggee' => array(),
6165
- 'gift' => array(),
6166
- 'gifts' => array(),
6167
- 'gives' => array(),
6168
- 'glass' => array(),
6169
- 'gle' => array(),
6170
- 'global' => array(),
6171
- 'globo' => array(),
6172
- 'gmail' => array(),
6173
- 'gmo' => array(),
6174
- 'gmx' => array(),
6175
- 'google' => array(),
6176
- 'gop' => array(),
6177
- 'graphics' => array(),
6178
- 'gratis' => array(),
6179
- 'green' => array(),
6180
- 'gripe' => array(),
6181
- 'group' => array(),
6182
- 'guge' => array(),
6183
- 'guide' => array(),
6184
- 'guitars' => array(),
6185
- 'guru' => array(),
6186
- 'hamburg' => array(),
6187
- 'haus' => array(),
6188
- 'healthcare' => array(),
6189
- 'help' => array(),
6190
- 'here' => array(),
6191
- 'hermes' => array(),
6192
- 'hiphop' => array(),
6193
- 'hiv' => array(),
6194
- 'holdings' => array(),
6195
- 'holiday' => array(),
6196
- 'homes' => array(),
6197
- 'horse' => array(),
6198
- 'host' => array(),
6199
- 'hosting' => array(),
6200
- 'house' => array(),
6201
- 'how' => array(),
6202
- 'ibm' => array(),
6203
- 'ifm' => array(),
6204
- 'iinet' => array(),
6205
- 'immo' => array(),
6206
- 'immobilien' => array(),
6207
- 'industries' => array(),
6208
- 'infiniti' => array(),
6209
- 'ing' => array(),
6210
- 'ink' => array(),
6211
- 'institute' => array(),
6212
- 'insure' => array(),
6213
- 'international' => array(),
6214
- 'investments' => array(),
6215
- 'ipiranga' => array(),
6216
- 'irish' => array(),
6217
- 'ist' => array(),
6218
- 'istanbul' => array(),
6219
- 'iwc' => array(),
6220
- 'java' => array(),
6221
- 'jetzt' => array(),
6222
- 'joburg' => array(),
6223
- 'juegos' => array(),
6224
- 'kaufen' => array(),
6225
- 'kim' => array(),
6226
- 'kitchen' => array(),
6227
- 'kiwi' => array(),
6228
- 'koeln' => array(),
6229
- 'krd' => array(),
6230
- 'kred' => array(),
6231
- 'lacaixa' => array(),
6232
- 'land' => array(),
6233
- 'latrobe' => array(),
6234
- 'lawyer' => array(),
6235
- 'lds' => array(),
6236
- 'lease' => array(),
6237
- 'leclerc' => array(),
6238
- 'lgbt' => array(),
6239
- 'life' => array(),
6240
- 'lighting' => array(),
6241
- 'limited' => array(),
6242
- 'limo' => array(),
6243
- 'link' => array(),
6244
- 'loans' => array(),
6245
- 'london' => array(),
6246
- 'lotto' => array(),
6247
- 'ltda' => array(),
6248
- 'luxe' => array(),
6249
- 'luxury' => array(),
6250
- 'madrid' => array(),
6251
- 'maison' => array(),
6252
- 'management' => array(),
6253
- 'mango' => array(),
6254
- 'market' => array(),
6255
- 'marketing' => array(),
6256
- 'media' => array(),
6257
- 'meet' => array(),
6258
- 'melbourne' => array(),
6259
- 'meme' => array(),
6260
- 'menu' => array(),
6261
- 'miami' => array(),
6262
- 'mini' => array(),
6263
- 'moda' => array(),
6264
- 'moe' => array(),
6265
- 'monash' => array(),
6266
- 'montblanc' => array(),
6267
- 'mormon' => array(),
6268
- 'mortgage' => array(),
6269
- 'moscow' => array(),
6270
- 'motorcycles' => array(),
6271
- 'mov' => array(),
6272
- 'nagoya' => array(),
6273
- 'navy' => array(),
6274
- 'netbank' => array(),
6275
- 'network' => array(),
6276
- 'neustar' => array(),
6277
- 'new' => array(),
6278
- 'nexus' => array(),
6279
- 'ngo' => array(),
6280
- 'nhk' => array(),
6281
- 'ninja' => array(),
6282
- 'nissan' => array(),
6283
- 'nra' => array(),
6284
- 'nrw' => array(),
6285
- 'nyc' => array(),
6286
- 'okinawa' => array(),
6287
- 'ong' => array(),
6288
- 'onl' => array(),
6289
- 'ooo' => array(),
6290
- 'oracle' => array(),
6291
- 'organic' => array(),
6292
- 'otsuka' => array(),
6293
- 'ovh' => array(),
6294
- 'paris' => array(),
6295
- 'partners' => array(),
6296
- 'parts' => array(),
6297
- 'pharmacy' => array(),
6298
- 'photo' => array(),
6299
- 'photography' => array(),
6300
- 'photos' => array(),
6301
- 'physio' => array(),
6302
- 'pics' => array(),
6303
- 'pictet' => array(),
6304
- 'pictures' => array(),
6305
- 'pink' => array(),
6306
- 'pizza' => array(),
6307
- 'place' => array(),
6308
- 'plumbing' => array(),
6309
- 'pohl' => array(),
6310
- 'poker' => array(),
6311
- 'praxi' => array(),
6312
- 'press' => array(),
6313
- 'prod' => array(),
6314
- 'productions' => array(),
6315
- 'prof' => array(),
6316
- 'properties' => array(),
6317
- 'property' => array(),
6318
- 'pub' => array(),
6319
- 'qpon' => array(),
6320
- 'quebec' => array(),
6321
- 'realtor' => array(),
6322
- 'recipes' => array(),
6323
- 'red' => array(),
6324
- 'rehab' => array(),
6325
- 'reise' => array(),
6326
- 'reisen' => array(),
6327
- 'ren' => array(),
6328
- 'rentals' => array(),
6329
- 'repair' => array(),
6330
- 'report' => array(),
6331
- 'republican' => array(),
6332
- 'rest' => array(),
6333
- 'restaurant' => array(),
6334
- 'reviews' => array(),
6335
- 'rich' => array(),
6336
- 'rio' => array(),
6337
- 'rip' => array(),
6338
- 'rocks' => array(),
6339
- 'rodeo' => array(),
6340
- 'rsvp' => array(),
6341
- 'ruhr' => array(),
6342
- 'ryukyu' => array(),
6343
- 'saarland' => array(),
6344
- 'samsung' => array(),
6345
- 'sap' => array(),
6346
- 'sarl' => array(),
6347
- 'sca' => array(),
6348
- 'scb' => array(),
6349
- 'schmidt' => array(),
6350
- 'scholarships' => array(),
6351
- 'schule' => array(),
6352
- 'scot' => array(),
6353
- 'seat' => array(),
6354
- 'services' => array(),
6355
- 'sew' => array(),
6356
- 'sexy' => array(),
6357
- 'sharp' => array(),
6358
- 'shiksha' => array(),
6359
- 'shoes' => array(),
6360
- 'shriram' => array(),
6361
- 'singles' => array(),
6362
- 'sky' => array(),
6363
- 'social' => array(),
6364
- 'software' => array(),
6365
- 'sohu' => array(),
6366
- 'solar' => array(),
6367
- 'solutions' => array(),
6368
- 'soy' => array(),
6369
- 'space' => array(),
6370
- 'spiegel' => array(),
6371
- 'supplies' => array(),
6372
- 'supply' => array(),
6373
- 'support' => array(),
6374
- 'surf' => array(),
6375
- 'surgery' => array(),
6376
- 'suzuki' => array(),
6377
- 'systems' => array(),
6378
- 'taipei' => array(),
6379
- 'tatar' => array(),
6380
- 'tattoo' => array(),
6381
- 'tax' => array(),
6382
- 'technology' => array(),
6383
- 'temasek' => array(),
6384
- 'tienda' => array(),
6385
- 'tips' => array(),
6386
- 'tirol' => array(),
6387
- 'today' => array(),
6388
- 'tokyo' => array(),
6389
- 'tools' => array(),
6390
- 'top' => array(),
6391
- 'toshiba' => array(),
6392
- 'town' => array(),
6393
- 'toys' => array(),
6394
- 'trade' => array(),
6395
- 'training' => array(),
6396
- 'tui' => array(),
6397
- 'university' => array(),
6398
- 'uno' => array(),
6399
- 'uol' => array(),
6400
- 'vacations' => array(),
6401
- 'vegas' => array(),
6402
- 'ventures' => array(),
6403
- 'versicherung' => array(),
6404
- 'vet' => array(),
6405
- 'viajes' => array(),
6406
- 'villas' => array(),
6407
- 'vision' => array(),
6408
- 'vlaanderen' => array(),
6409
- 'vodka' => array(),
6410
- 'vote' => array(),
6411
- 'voting' => array(),
6412
- 'voto' => array(),
6413
- 'voyage' => array(),
6414
- 'wales' => array(),
6415
- 'wang' => array(),
6416
- 'watch' => array(),
6417
- 'webcam' => array(),
6418
- 'website' => array(),
6419
- 'wed' => array(),
6420
- 'wedding' => array(),
6421
- 'whoswho' => array(),
6422
- 'wien' => array(),
6423
- 'wiki' => array(),
6424
- 'williamhill' => array(),
6425
- 'wme' => array(),
6426
- 'work' => array(),
6427
- 'works' => array(),
6428
- 'world' => array(),
6429
- 'wtc' => array(),
6430
- 'wtf' => array(),
6431
- '佛山' => array(),
6432
- '慈善' => array(),
6433
- '集团' => array(),
6434
- '在线' => array(),
6435
- '八卦' => array(),
6436
- 'موقع' => array(),
6437
- '公益' => array(),
6438
- '公司' => array(),
6439
- '移动' => array(),
6440
- '我爱你' => array(),
6441
- 'москва' => array(),
6442
- 'онлайн' => array(),
6443
- 'сайт' => array(),
6444
- '时尚' => array(),
6445
- '淡马锡' => array(),
6446
- 'орг' => array(),
6447
- '삼성' => array(),
6448
- '商标' => array(),
6449
- '商店' => array(),
6450
- '商城' => array(),
6451
- 'дети' => array(),
6452
- '新闻' => array(),
6453
- '中文网' => array(),
6454
- '中信' => array(),
6455
- '娱乐' => array(),
6456
- '谷歌' => array(),
6457
- '网店' => array(),
6458
- 'संगठन' => array(),
6459
- '网络' => array(),
6460
- '手机' => array(),
6461
- 'بازار' => array(),
6462
- '政府' => array(),
6463
- 'شبكة' => array(),
6464
- '机构' => array(),
6465
- '组织机构' => array(),
6466
- 'рус' => array(),
6467
- 'みんな' => array(),
6468
- 'グーグル' => array(),
6469
- '世界' => array(),
6470
- '网址' => array(),
6471
- '游戏' => array(),
6472
- 'vermögensberater' => array(),
6473
- 'vermögensberatung' => array(),
6474
- '企业' => array(),
6475
- '广东' => array(),
6476
- '政务' => array(),
6477
- 'xyz' => array(),
6478
- 'yachts' => array(),
6479
- 'yandex' => array(),
6480
- 'yoga' => array(),
6481
- 'yokohama' => array(),
6482
- 'youtube' => array(),
6483
- 'zip' => array(),
6484
- 'zone' => array());
1
+ <?php
2
+ // This Source Code Form is subject to the terms of the Mozilla Public
3
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
4
+ // file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
+
6
+ $tldTree = array('ac' => array('com' => array(),
7
+ 'edu' => array(),
8
+ 'gov' => array(),
9
+ 'net' => array(),
10
+ 'mil' => array(),
11
+ 'org' => array()),
12
+ 'ad' => array('nom' => array()),
13
+ 'ae' => array('co' => array(),
14
+ 'net' => array(),
15
+ 'org' => array(),
16
+ 'sch' => array(),
17
+ 'ac' => array(),
18
+ 'gov' => array(),
19
+ 'mil' => array()),
20
+ 'aero' => array('accident-investigation' => array(),
21
+ 'accident-prevention' => array(),
22
+ 'aerobatic' => array(),
23
+ 'aeroclub' => array(),
24
+ 'aerodrome' => array(),
25
+ 'agents' => array(),
26
+ 'aircraft' => array(),
27
+ 'airline' => array(),
28
+ 'airport' => array(),
29
+ 'air-surveillance' => array(),
30
+ 'airtraffic' => array(),
31
+ 'air-traffic-control' => array(),
32
+ 'ambulance' => array(),
33
+ 'amusement' => array(),
34
+ 'association' => array(),
35
+ 'author' => array(),
36
+ 'ballooning' => array(),
37
+ 'broker' => array(),
38
+ 'caa' => array(),
39
+ 'cargo' => array(),
40
+ 'catering' => array(),
41
+ 'certification' => array(),
42
+ 'championship' => array(),
43
+ 'charter' => array(),
44
+ 'civilaviation' => array(),
45
+ 'club' => array(),
46
+ 'conference' => array(),
47
+ 'consultant' => array(),
48
+ 'consulting' => array(),
49
+ 'control' => array(),
50
+ 'council' => array(),
51
+ 'crew' => array(),
52
+ 'design' => array(),
53
+ 'dgca' => array(),
54
+ 'educator' => array(),
55
+ 'emergency' => array(),
56
+ 'engine' => array(),
57
+ 'engineer' => array(),
58
+ 'entertainment' => array(),
59
+ 'equipment' => array(),
60
+ 'exchange' => array(),
61
+ 'express' => array(),
62
+ 'federation' => array(),
63
+ 'flight' => array(),
64
+ 'freight' => array(),
65
+ 'fuel' => array(),
66
+ 'gliding' => array(),
67
+ 'government' => array(),
68
+ 'groundhandling' => array(),
69
+ 'group' => array(),
70
+ 'hanggliding' => array(),
71
+ 'homebuilt' => array(),
72
+ 'insurance' => array(),
73
+ 'journal' => array(),
74
+ 'journalist' => array(),
75
+ 'leasing' => array(),
76
+ 'logistics' => array(),
77
+ 'magazine' => array(),
78
+ 'maintenance' => array(),
79
+ 'marketplace' => array(),
80
+ 'media' => array(),
81
+ 'microlight' => array(),
82
+ 'modelling' => array(),
83
+ 'navigation' => array(),
84
+ 'parachuting' => array(),
85
+ 'paragliding' => array(),
86
+ 'passenger-association' => array(),
87
+ 'pilot' => array(),
88
+ 'press' => array(),
89
+ 'production' => array(),
90
+ 'recreation' => array(),
91
+ 'repbody' => array(),
92
+ 'res' => array(),
93
+ 'research' => array(),
94
+ 'rotorcraft' => array(),
95
+ 'safety' => array(),
96
+ 'scientist' => array(),
97
+ 'services' => array(),
98
+ 'show' => array(),
99
+ 'skydiving' => array(),
100
+ 'software' => array(),
101
+ 'student' => array(),
102
+ 'taxi' => array(),
103
+ 'trader' => array(),
104
+ 'trading' => array(),
105
+ 'trainer' => array(),
106
+ 'union' => array(),
107
+ 'workinggroup' => array(),
108
+ 'works' => array()),
109
+ 'af' => array('gov' => array(),
110
+ 'com' => array(),
111
+ 'org' => array(),
112
+ 'net' => array(),
113
+ 'edu' => array()),
114
+ 'ag' => array('com' => array(),
115
+ 'org' => array(),
116
+ 'net' => array(),
117
+ 'co' => array(),
118
+ 'nom' => array()),
119
+ 'ai' => array('off' => array(),
120
+ 'com' => array(),
121
+ 'net' => array(),
122
+ 'org' => array()),
123
+ 'al' => array('com' => array(),
124
+ 'edu' => array(),
125
+ 'gov' => array(),
126
+ 'mil' => array(),
127
+ 'net' => array(),
128
+ 'org' => array()),
129
+ 'am' => array(),
130
+ 'an' => array('com' => array(),
131
+ 'net' => array(),
132
+ 'org' => array(),
133
+ 'edu' => array()),
134
+ 'ao' => array('ed' => array(),
135
+ 'gv' => array(),
136
+ 'og' => array(),
137
+ 'co' => array(),
138
+ 'pb' => array(),
139
+ 'it' => array()),
140
+ 'aq' => array(),
141
+ 'ar' => array('com' => array('blogspot' => array()),
142
+ 'edu' => array(),
143
+ 'gob' => array(),
144
+ 'gov' => array(),
145
+ 'int' => array(),
146
+ 'mil' => array(),
147
+ 'net' => array(),
148
+ 'org' => array(),
149
+ 'tur' => array()),
150
+ 'arpa' => array('e164' => array(),
151
+ 'in-addr' => array(),
152
+ 'ip6' => array(),
153
+ 'iris' => array(),
154
+ 'uri' => array(),
155
+ 'urn' => array()),
156
+ 'as' => array('gov' => array()),
157
+ 'asia' => array(),
158
+ 'at' => array('ac' => array(),
159
+ 'co' => array('blogspot' => array()),
160
+ 'gv' => array(),
161
+ 'or' => array(),
162
+ 'biz' => array(),
163
+ 'info' => array(),
164
+ 'priv' => array()),
165
+ 'au' => array('com' => array('blogspot' => array()),
166
+ 'net' => array(),
167
+ 'org' => array(),
168
+ 'edu' => array('act' => array(),
169
+ 'nsw' => array(),
170
+ 'nt' => array(),
171
+ 'qld' => array(),
172
+ 'sa' => array(),
173
+ 'tas' => array(),
174
+ 'vic' => array(),
175
+ 'wa' => array()),
176
+ 'gov' => array('qld' => array(),
177
+ 'sa' => array(),
178
+ 'tas' => array(),
179
+ 'vic' => array(),
180
+ 'wa' => array()),
181
+ 'asn' => array(),
182
+ 'id' => array(),
183
+ 'info' => array(),
184
+ 'conf' => array(),
185
+ 'oz' => array(),
186
+ 'act' => array(),
187
+ 'nsw' => array(),
188
+ 'nt' => array(),
189
+ 'qld' => array(),
190
+ 'sa' => array(),
191
+ 'tas' => array(),
192
+ 'vic' => array(),
193
+ 'wa' => array()),
194
+ 'aw' => array('com' => array()),
195
+ 'ax' => array(),
196
+ 'az' => array('com' => array(),
197
+ 'net' => array(),
198
+ 'int' => array(),
199
+ 'gov' => array(),
200
+ 'org' => array(),
201
+ 'edu' => array(),
202
+ 'info' => array(),
203
+ 'pp' => array(),
204
+ 'mil' => array(),
205
+ 'name' => array(),
206
+ 'pro' => array(),
207
+ 'biz' => array()),
208
+ 'ba' => array('org' => array(),
209
+ 'net' => array(),
210
+ 'edu' => array(),
211
+ 'gov' => array(),
212
+ 'mil' => array(),
213
+ 'unsa' => array(),
214
+ 'unbi' => array(),
215
+ 'co' => array(),
216
+ 'com' => array(),
217
+ 'rs' => array()),
218
+ 'bb' => array('biz' => array(),
219
+ 'co' => array(),
220
+ 'com' => array(),
221
+ 'edu' => array(),
222
+ 'gov' => array(),
223
+ 'info' => array(),
224
+ 'net' => array(),
225
+ 'org' => array(),
226
+ 'store' => array(),
227
+ 'tv' => array()),
228
+ 'bd' => array('*' => array()),
229
+ 'be' => array('ac' => array(),
230
+ 'blogspot' => array()),
231
+ 'bf' => array('gov' => array()),
232
+ 'bg' => array('a' => array(),
233
+ 'b' => array(),
234
+ 'c' => array(),
235
+ 'd' => array(),
236
+ 'e' => array(),
237
+ 'f' => array(),
238
+ 'g' => array(),
239
+ 'h' => array(),
240
+ 'i' => array(),
241
+ 'j' => array(),
242
+ 'k' => array(),
243
+ 'l' => array(),
244
+ 'm' => array(),
245
+ 'n' => array(),
246
+ 'o' => array(),
247
+ 'p' => array(),
248
+ 'q' => array(),
249
+ 'r' => array(),
250
+ 's' => array(),
251
+ 't' => array(),
252
+ 'u' => array(),
253
+ 'v' => array(),
254
+ 'w' => array(),
255
+ 'x' => array(),
256
+ 'y' => array(),
257
+ 'z' => array(),
258
+ '0' => array(),
259
+ '1' => array(),
260
+ '2' => array(),
261
+ '3' => array(),
262
+ '4' => array(),
263
+ '5' => array(),
264
+ '6' => array(),
265
+ '7' => array(),
266
+ '8' => array(),
267
+ '9' => array()),
268
+ 'bh' => array('com' => array(),
269
+ 'edu' => array(),
270
+ 'net' => array(),
271
+ 'org' => array(),
272
+ 'gov' => array()),
273
+ 'bi' => array('co' => array(),
274
+ 'com' => array(),
275
+ 'edu' => array(),
276
+ 'or' => array(),
277
+ 'org' => array()),
278
+ 'biz' => array('dyndns' => array(),
279
+ 'for-better' => array(),
280
+ 'for-more' => array(),
281
+ 'for-some' => array(),
282
+ 'for-the' => array(),
283
+ 'selfip' => array(),
284
+ 'webhop' => array()),
285
+ 'bj' => array('asso' => array(),
286
+ 'barreau' => array(),
287
+ 'gouv' => array(),
288
+ 'blogspot' => array()),
289
+ 'bm' => array('com' => array(),
290
+ 'edu' => array(),
291
+ 'gov' => array(),
292
+ 'net' => array(),
293
+ 'org' => array()),
294
+ 'bn' => array('*' => array()),
295
+ 'bo' => array('com' => array(),
296
+ 'edu' => array(),
297
+ 'gov' => array(),
298
+ 'gob' => array(),
299
+ 'int' => array(),
300
+ 'org' => array(),
301
+ 'net' => array(),
302
+ 'mil' => array(),
303
+ 'tv' => array()),
304
+ 'br' => array('adm' => array(),
305
+ 'adv' => array(),
306
+ 'agr' => array(),
307
+ 'am' => array(),
308
+ 'arq' => array(),
309
+ 'art' => array(),
310
+ 'ato' => array(),
311
+ 'b' => array(),
312
+ 'bio' => array(),
313
+ 'blog' => array(),
314
+ 'bmd' => array(),
315
+ 'cim' => array(),
316
+ 'cng' => array(),
317
+ 'cnt' => array(),
318
+ 'com' => array('blogspot' => array()),
319
+ 'coop' => array(),
320
+ 'ecn' => array(),
321
+ 'eco' => array(),
322
+ 'edu' => array(),
323
+ 'emp' => array(),
324
+ 'eng' => array(),
325
+ 'esp' => array(),
326
+ 'etc' => array(),
327
+ 'eti' => array(),
328
+ 'far' => array(),
329
+ 'flog' => array(),
330
+ 'fm' => array(),
331
+ 'fnd' => array(),
332
+ 'fot' => array(),
333
+ 'fst' => array(),
334
+ 'g12' => array(),
335
+ 'ggf' => array(),
336
+ 'gov' => array(),
337
+ 'imb' => array(),
338
+ 'ind' => array(),
339
+ 'inf' => array(),
340
+ 'jor' => array(),
341
+ 'jus' => array(),
342
+ 'leg' => array(),
343
+ 'lel' => array(),
344
+ 'mat' => array(),
345
+ 'med' => array(),
346
+ 'mil' => array(),
347
+ 'mp' => array(),
348
+ 'mus' => array(),
349
+ 'net' => array(),
350
+ 'nom' => array('*' => array()),
351
+ 'not' => array(),
352
+ 'ntr' => array(),
353
+ 'odo' => array(),
354
+ 'org' => array(),
355
+ 'ppg' => array(),
356
+ 'pro' => array(),
357
+ 'psc' => array(),
358
+ 'psi' => array(),
359
+ 'qsl' => array(),
360
+ 'radio' => array(),
361
+ 'rec' => array(),
362
+ 'slg' => array(),
363
+ 'srv' => array(),
364
+ 'taxi' => array(),
365
+ 'teo' => array(),
366
+ 'tmp' => array(),
367
+ 'trd' => array(),
368
+ 'tur' => array(),
369
+ 'tv' => array(),
370
+ 'vet' => array(),
371
+ 'vlog' => array(),
372
+ 'wiki' => array(),
373
+ 'zlg' => array()),
374
+ 'bs' => array('com' => array(),
375
+ 'net' => array(),
376
+ 'org' => array(),
377
+ 'edu' => array(),
378
+ 'gov' => array()),
379
+ 'bt' => array('com' => array(),
380
+ 'edu' => array(),
381
+ 'gov' => array(),
382
+ 'net' => array(),
383
+ 'org' => array()),
384
+ 'bv' => array(),
385
+ 'bw' => array('co' => array(),
386
+ 'org' => array()),
387
+ 'by' => array('gov' => array(),
388
+ 'mil' => array(),
389
+ 'com' => array(),
390
+ 'of' => array()),
391
+ 'bz' => array('com' => array(),
392
+ 'net' => array(),
393
+ 'org' => array(),
394
+ 'edu' => array(),
395
+ 'gov' => array(),
396
+ 'za' => array()),
397
+ 'ca' => array('ab' => array(),
398
+ 'bc' => array(),
399
+ 'mb' => array(),
400
+ 'nb' => array(),
401
+ 'nf' => array(),
402
+ 'nl' => array(),
403
+ 'ns' => array(),
404
+ 'nt' => array(),
405
+ 'nu' => array(),
406
+ 'on' => array(),
407
+ 'pe' => array(),
408
+ 'qc' => array(),
409
+ 'sk' => array(),
410
+ 'yk' => array(),
411
+ 'gc' => array(),
412
+ 'co' => array(),
413
+ 'blogspot' => array()),
414
+ 'cat' => array(),
415
+ 'cc' => array('ftpaccess' => array(),
416
+ 'game-server' => array(),
417
+ 'myphotos' => array(),
418
+ 'scrapping' => array()),
419
+ 'cd' => array('gov' => array()),
420
+ 'cf' => array('blogspot' => array()),
421
+ 'cg' => array(),
422
+ 'ch' => array('blogspot' => array()),
423
+ 'ci' => array('org' => array(),
424
+ 'or' => array(),
425
+ 'com' => array(),
426
+ 'co' => array(),
427
+ 'edu' => array(),
428
+ 'ed' => array(),
429
+ 'ac' => array(),
430
+ 'net' => array(),
431
+ 'go' => array(),
432
+ 'asso' => array(),
433
+ 'aéroport' => array(),
434
+ 'int' => array(),
435
+ 'presse' => array(),
436
+ 'md' => array(),
437
+ 'gouv' => array()),
438
+ 'ck' => array('*' => array(),
439
+ 'www' => array('!' => '')),
440
+ 'cl' => array('gov' => array(),
441
+ 'gob' => array(),
442
+ 'co' => array(),
443
+ 'mil' => array()),
444
+ 'cm' => array('co' => array(),
445
+ 'com' => array(),
446
+ 'gov' => array(),
447
+ 'net' => array()),
448
+ 'cn' => array('ac' => array(),
449
+ 'com' => array(),
450
+ 'edu' => array(),
451
+ 'gov' => array(),
452
+ 'net' => array(),
453
+ 'org' => array(),
454
+ 'mil' => array(),
455
+ '公司' => array(),
456
+ '网络' => array(),
457
+ '網絡' => array(),
458
+ 'ah' => array(),
459
+ 'bj' => array(),
460
+ 'cq' => array(),
461
+ 'fj' => array(),
462
+ 'gd' => array(),
463
+ 'gs' => array(),
464
+ 'gz' => array(),
465
+ 'gx' => array(),
466
+ 'ha' => array(),
467
+ 'hb' => array(),
468
+ 'he' => array(),
469
+ 'hi' => array(),
470
+ 'hl' => array(),
471
+ 'hn' => array(),
472
+ 'jl' => array(),
473
+ 'js' => array(),
474
+ 'jx' => array(),
475
+ 'ln' => array(),
476
+ 'nm' => array(),
477
+ 'nx' => array(),
478
+ 'qh' => array(),
479
+ 'sc' => array(),
480
+ 'sd' => array(),
481
+ 'sh' => array(),
482
+ 'sn' => array(),
483
+ 'sx' => array(),
484
+ 'tj' => array(),
485
+ 'xj' => array(),
486
+ 'xz' => array(),
487
+ 'yn' => array(),
488
+ 'zj' => array(),
489
+ 'hk' => array(),
490
+ 'mo' => array(),
491
+ 'tw' => array(),
492
+ 'amazonaws' => array('compute' => array('cn-north-1' => array()))),
493
+ 'co' => array('arts' => array(),
494
+ 'com' => array(),
495
+ 'edu' => array(),
496
+ 'firm' => array(),
497
+ 'gov' => array(),
498
+ 'info' => array(),
499
+ 'int' => array(),
500
+ 'mil' => array(),
501
+ 'net' => array(),
502
+ 'nom' => array(),
503
+ 'org' => array(),
504
+ 'rec' => array(),
505
+ 'web' => array()),
506
+ 'com' => array('amazonaws' => array('compute' => array('ap-northeast-1' => array(),
507
+ 'ap-southeast-1' => array(),
508
+ 'ap-southeast-2' => array(),
509
+ 'eu-west-1' => array(),
510
+ 'sa-east-1' => array(),
511
+ 'us-gov-west-1' => array(),
512
+ 'us-west-1' => array(),
513
+ 'us-west-2' => array()),
514
+ 'compute-1' => array('z-1' => array(),
515
+ 'z-2' => array()),
516
+ 'us-east-1' => array(),
517
+ 'elb' => array(),
518
+ 's3' => array(),
519
+ 's3-us-west-2' => array(),
520
+ 's3-us-west-1' => array(),
521
+ 's3-eu-west-1' => array(),
522
+ 's3-ap-southeast-1' => array(),
523
+ 's3-ap-southeast-2' => array(),
524
+ 's3-ap-northeast-1' => array(),
525
+ 's3-sa-east-1' => array(),
526
+ 's3-us-gov-west-1' => array(),
527
+ 's3-fips-us-gov-west-1' => array(),
528
+ 's3-website-us-east-1' => array(),
529
+ 's3-website-us-west-2' => array(),
530
+ 's3-website-us-west-1' => array(),
531
+ 's3-website-eu-west-1' => array(),
532
+ 's3-website-ap-southeast-1' => array(),
533
+ 's3-website-ap-southeast-2' => array(),
534
+ 's3-website-ap-northeast-1' => array(),
535
+ 's3-website-sa-east-1' => array(),
536
+ 's3-website-us-gov-west-1' => array()),
537
+ 'elasticbeanstalk' => array(),
538
+ 'betainabox' => array(),
539
+ 'ar' => array(),
540
+ 'br' => array(),
541
+ 'cn' => array(),
542
+ 'de' => array(),
543
+ 'eu' => array(),
544
+ 'gb' => array(),
545
+ 'hu' => array(),
546
+ 'jpn' => array(),
547
+ 'kr' => array(),
548
+ 'mex' => array(),
549
+ 'no' => array(),
550
+ 'qc' => array(),
551
+ 'ru' => array(),
552
+ 'sa' => array(),
553
+ 'se' => array(),
554
+ 'uk' => array(),
555
+ 'us' => array(),
556
+ 'uy' => array(),
557
+ 'za' => array(),
558
+ 'africa' => array(),
559
+ 'gr' => array(),
560
+ 'co' => array(),
561
+ 'cloudcontrolled' => array(),
562
+ 'cloudcontrolapp' => array(),
563
+ 'dreamhosters' => array(),
564
+ 'dyndns-at-home' => array(),
565
+ 'dyndns-at-work' => array(),
566
+ 'dyndns-blog' => array(),
567
+ 'dyndns-free' => array(),
568
+ 'dyndns-home' => array(),
569
+ 'dyndns-ip' => array(),
570
+ 'dyndns-mail' => array(),
571
+ 'dyndns-office' => array(),
572
+ 'dyndns-pics' => array(),
573
+ 'dyndns-remote' => array(),
574
+ 'dyndns-server' => array(),
575
+ 'dyndns-web' => array(),
576
+ 'dyndns-wiki' => array(),
577
+ 'dyndns-work' => array(),
578
+ 'blogdns' => array(),
579
+ 'cechire' => array(),
580
+ 'dnsalias' => array(),
581
+ 'dnsdojo' => array(),
582
+ 'doesntexist' => array(),
583
+ 'dontexist' => array(),
584
+ 'doomdns' => array(),
585
+ 'dyn-o-saur' => array(),
586
+ 'dynalias' => array(),
587
+ 'est-a-la-maison' => array(),
588
+ 'est-a-la-masion' => array(),
589
+ 'est-le-patron' => array(),
590
+ 'est-mon-blogueur' => array(),
591
+ 'from-ak' => array(),
592
+ 'from-al' => array(),
593
+ 'from-ar' => array(),
594
+ 'from-ca' => array(),
595
+ 'from-ct' => array(),
596
+ 'from-dc' => array(),
597
+ 'from-de' => array(),
598
+ 'from-fl' => array(),
599
+ 'from-ga' => array(),
600
+ 'from-hi' => array(),
601
+ 'from-ia' => array(),
602
+ 'from-id' => array(),
603
+ 'from-il' => array(),
604
+ 'from-in' => array(),
605
+ 'from-ks' => array(),
606
+ 'from-ky' => array(),
607
+ 'from-ma' => array(),
608
+ 'from-md' => array(),
609
+ 'from-mi' => array(),
610
+ 'from-mn' => array(),
611
+ 'from-mo' => array(),
612
+ 'from-ms' => array(),
613
+ 'from-mt' => array(),
614
+ 'from-nc' => array(),
615
+ 'from-nd' => array(),
616
+ 'from-ne' => array(),
617
+ 'from-nh' => array(),
618
+ 'from-nj' => array(),
619
+ 'from-nm' => array(),
620
+ 'from-nv' => array(),
621
+ 'from-oh' => array(),
622
+ 'from-ok' => array(),
623
+ 'from-or' => array(),
624
+ 'from-pa' => array(),
625
+ 'from-pr' => array(),
626
+ 'from-ri' => array(),
627
+ 'from-sc' => array(),
628
+ 'from-sd' => array(),
629
+ 'from-tn' => array(),
630
+ 'from-tx' => array(),
631
+ 'from-ut' => array(),
632
+ 'from-va' => array(),
633
+ 'from-vt' => array(),
634
+ 'from-wa' => array(),
635
+ 'from-wi' => array(),
636
+ 'from-wv' => array(),
637
+ 'from-wy' => array(),
638
+ 'getmyip' => array(),
639
+ 'gotdns' => array(),
640
+ 'hobby-site' => array(),
641
+ 'homelinux' => array(),
642
+ 'homeunix' => array(),
643
+ 'iamallama' => array(),
644
+ 'is-a-anarchist' => array(),
645
+ 'is-a-blogger' => array(),
646
+ 'is-a-bookkeeper' => array(),
647
+ 'is-a-bulls-fan' => array(),
648
+ 'is-a-caterer' => array(),
649
+ 'is-a-chef' => array(),
650
+ 'is-a-conservative' => array(),
651
+ 'is-a-cpa' => array(),
652
+ 'is-a-cubicle-slave' => array(),
653
+ 'is-a-democrat' => array(),
654
+ 'is-a-designer' => array(),
655
+ 'is-a-doctor' => array(),
656
+ 'is-a-financialadvisor' => array(),
657
+ 'is-a-geek' => array(),
658
+ 'is-a-green' => array(),
659
+ 'is-a-guru' => array(),
660
+ 'is-a-hard-worker' => array(),
661
+ 'is-a-hunter' => array(),
662
+ 'is-a-landscaper' => array(),
663
+ 'is-a-lawyer' => array(),
664
+ 'is-a-liberal' => array(),
665
+ 'is-a-libertarian' => array(),
666
+ 'is-a-llama' => array(),
667
+ 'is-a-musician' => array(),
668
+ 'is-a-nascarfan' => array(),
669
+ 'is-a-nurse' => array(),
670
+ 'is-a-painter' => array(),
671
+ 'is-a-personaltrainer' => array(),
672
+ 'is-a-photographer' => array(),
673
+ 'is-a-player' => array(),
674
+ 'is-a-republican' => array(),
675
+ 'is-a-rockstar' => array(),
676
+ 'is-a-socialist' => array(),
677
+ 'is-a-student' => array(),
678
+ 'is-a-teacher' => array(),
679
+ 'is-a-techie' => array(),
680
+ 'is-a-therapist' => array(),
681
+ 'is-an-accountant' => array(),
682
+ 'is-an-actor' => array(),
683
+ 'is-an-actress' => array(),
684
+ 'is-an-anarchist' => array(),
685
+ 'is-an-artist' => array(),
686
+ 'is-an-engineer' => array(),
687
+ 'is-an-entertainer' => array(),
688
+ 'is-certified' => array(),
689
+ 'is-gone' => array(),
690
+ 'is-into-anime' => array(),
691
+ 'is-into-cars' => array(),
692
+ 'is-into-cartoons' => array(),
693
+ 'is-into-games' => array(),
694
+ 'is-leet' => array(),
695
+ 'is-not-certified' => array(),
696
+ 'is-slick' => array(),
697
+ 'is-uberleet' => array(),
698
+ 'is-with-theband' => array(),
699
+ 'isa-geek' => array(),
700
+ 'isa-hockeynut' => array(),
701
+ 'issmarterthanyou' => array(),
702
+ 'likes-pie' => array(),
703
+ 'likescandy' => array(),
704
+ 'neat-url' => array(),
705
+ 'saves-the-whales' => array(),
706
+ 'selfip' => array(),
707
+ 'sells-for-less' => array(),
708
+ 'sells-for-u' => array(),
709
+ 'servebbs' => array(),
710
+ 'simple-url' => array(),
711
+ 'space-to-rent' => array(),
712
+ 'teaches-yoga' => array(),
713
+ 'writesthisblog' => array(),
714
+ 'firebaseapp' => array(),
715
+ 'flynnhub' => array(),
716
+ 'githubusercontent' => array(),
717
+ 'ro' => array(),
718
+ 'appspot' => array(),
719
+ 'blogspot' => array(),
720
+ 'codespot' => array(),
721
+ 'googleapis' => array(),
722
+ 'googlecode' => array(),
723
+ 'withgoogle' => array(),
724
+ 'herokuapp' => array(),
725
+ 'herokussl' => array(),
726
+ 'nfshost' => array(),
727
+ 'operaunite' => array(),
728
+ 'outsystemscloud' => array(),
729
+ 'rhcloud' => array(),
730
+ 'yolasite' => array()),
731
+ 'coop' => array(),
732
+ 'cr' => array('ac' => array(),
733
+ 'co' => array(),
734
+ 'ed' => array(),
735
+ 'fi' => array(),
736
+ 'go' => array(),
737
+ 'or' => array(),
738
+ 'sa' => array()),
739
+ 'cu' => array('com' => array(),
740
+ 'edu' => array(),
741
+ 'org' => array(),
742
+ 'net' => array(),
743
+ 'gov' => array(),
744
+ 'inf' => array()),
745
+ 'cv' => array('blogspot' => array()),
746
+ 'cw' => array('com' => array(),
747
+ 'edu' => array(),
748
+ 'net' => array(),
749
+ 'org' => array()),
750
+ 'cx' => array('gov' => array(),
751
+ 'ath' => array()),
752
+ 'cy' => array('*' => array()),
753
+ 'cz' => array('blogspot' => array()),
754
+ 'de' => array('com' => array(),
755
+ 'fuettertdasnetz' => array(),
756
+ 'isteingeek' => array(),
757
+ 'istmein' => array(),
758
+ 'lebtimnetz' => array(),
759
+ 'leitungsen' => array(),
760
+ 'traeumtgerade' => array(),
761
+ 'blogspot' => array()),
762
+ 'dj' => array(),
763
+ 'dk' => array('blogspot' => array()),
764
+ 'dm' => array('com' => array(),
765
+ 'net' => array(),
766
+ 'org' => array(),
767
+ 'edu' => array(),
768
+ 'gov' => array()),
769
+ 'do' => array('art' => array(),
770
+ 'com' => array(),
771
+ 'edu' => array(),
772
+ 'gob' => array(),
773
+ 'gov' => array(),
774
+ 'mil' => array(),
775
+ 'net' => array(),
776
+ 'org' => array(),
777
+ 'sld' => array(),
778
+ 'web' => array()),
779
+ 'dz' => array('com' => array(),
780
+ 'org' => array(),
781
+ 'net' => array(),
782
+ 'gov' => array(),
783
+ 'edu' => array(),
784
+ 'asso' => array(),
785
+ 'pol' => array(),
786
+ 'art' => array()),
787
+ 'ec' => array('com' => array(),
788
+ 'info' => array(),
789
+ 'net' => array(),
790
+ 'fin' => array(),
791
+ 'k12' => array(),
792
+ 'med' => array(),
793
+ 'pro' => array(),
794
+ 'org' => array(),
795
+ 'edu' => array(),
796
+ 'gov' => array(),
797
+ 'gob' => array(),
798
+ 'mil' => array()),
799
+ 'edu' => array(),
800
+ 'ee' => array('edu' => array(),
801
+ 'gov' => array(),
802
+ 'riik' => array(),
803
+ 'lib' => array(),
804
+ 'med' => array(),
805
+ 'com' => array(),
806
+ 'pri' => array(),
807
+ 'aip' => array(),
808
+ 'org' => array(),
809
+ 'fie' => array()),
810
+ 'eg' => array('com' => array(),
811
+ 'edu' => array(),
812
+ 'eun' => array(),
813
+ 'gov' => array(),
814
+ 'mil' => array(),
815
+ 'name' => array(),
816
+ 'net' => array(),
817
+ 'org' => array(),
818
+ 'sci' => array()),
819
+ 'er' => array('*' => array()),
820
+ 'es' => array('com' => array('blogspot' => array()),
821
+ 'nom' => array(),
822
+ 'org' => array(),
823
+ 'gob' => array(),
824
+ 'edu' => array()),
825
+ 'et' => array('com' => array(),
826
+ 'gov' => array(),
827
+ 'org' => array(),
828
+ 'edu' => array(),
829
+ 'biz' => array(),
830
+ 'name' => array(),
831
+ 'info' => array()),
832
+ 'eu' => array(),
833
+ 'fi' => array('aland' => array(),
834
+ 'blogspot' => array(),
835
+ 'iki' => array()),
836
+ 'fj' => array('*' => array()),
837
+ 'fk' => array('*' => array()),
838
+ 'fm' => array(),
839
+ 'fo' => array(),
840
+ 'fr' => array('com' => array(),
841
+ 'asso' => array(),
842
+ 'nom' => array(),
843
+ 'prd' => array(),
844
+ 'presse' => array(),
845
+ 'tm' => array(),
846
+ 'aeroport' => array(),
847
+ 'assedic' => array(),
848
+ 'avocat' => array(),
849
+ 'avoues' => array(),
850
+ 'cci' => array(),
851
+ 'chambagri' => array(),
852
+ 'chirurgiens-dentistes' => array(),
853
+ 'experts-comptables' => array(),
854
+ 'geometre-expert' => array(),
855
+ 'gouv' => array(),
856
+ 'greta' => array(),
857
+ 'huissier-justice' => array(),
858
+ 'medecin' => array(),
859
+ 'notaires' => array(),
860
+ 'pharmacien' => array(),
861
+ 'port' => array(),
862
+ 'veterinaire' => array(),
863
+ 'blogspot' => array()),
864
+ 'ga' => array(),
865
+ 'gb' => array(),
866
+ 'gd' => array(),
867
+ 'ge' => array('com' => array(),
868
+ 'edu' => array(),
869
+ 'gov' => array(),
870
+ 'org' => array(),
871
+ 'mil' => array(),
872
+ 'net' => array(),
873
+ 'pvt' => array()),
874
+ 'gf' => array(),
875
+ 'gg' => array('co' => array(),
876
+ 'net' => array(),
877
+ 'org' => array()),
878
+ 'gh' => array('com' => array(),
879
+ 'edu' => array(),
880
+ 'gov' => array(),
881
+ 'org' => array(),
882
+ 'mil' => array()),
883
+ 'gi' => array('com' => array(),
884
+ 'ltd' => array(),
885
+ 'gov' => array(),
886
+ 'mod' => array(),
887
+ 'edu' => array(),
888
+ 'org' => array()),
889
+ 'gl' => array(),
890
+ 'gm' => array(),
891
+ 'gn' => array('ac' => array(),
892
+ 'com' => array(),
893
+ 'edu' => array(),
894
+ 'gov' => array(),
895
+ 'org' => array(),
896
+ 'net' => array()),
897
+ 'gov' => array(),
898
+ 'gp' => array('com' => array(),
899
+ 'net' => array(),
900
+ 'mobi' => array(),
901
+ 'edu' => array(),
902
+ 'org' => array(),
903
+ 'asso' => array()),
904
+ 'gq' => array(),
905
+ 'gr' => array('com' => array(),
906
+ 'edu' => array(),
907
+ 'net' => array(),
908
+ 'org' => array(),
909
+ 'gov' => array(),
910
+ 'blogspot' => array()),
911
+ 'gs' => array(),
912
+ 'gt' => array('com' => array(),
913
+ 'edu' => array(),
914
+ 'gob' => array(),
915
+ 'ind' => array(),
916
+ 'mil' => array(),
917
+ 'net' => array(),
918
+ 'org' => array()),
919
+ 'gu' => array('*' => array()),
920
+ 'gw' => array(),
921
+ 'gy' => array('co' => array(),
922
+ 'com' => array(),
923
+ 'net' => array()),
924
+ 'hk' => array('com' => array(),
925
+ 'edu' => array(),
926
+ 'gov' => array(),
927
+ 'idv' => array(),
928
+ 'net' => array(),
929
+ 'org' => array(),
930
+ '公司' => array(),
931
+ '教育' => array(),
932
+ '敎育' => array(),
933
+ '政府' => array(),
934
+ '個人' => array(),
935
+ '个人' => array(),
936
+ '箇人' => array(),
937
+ '網络' => array(),
938
+ '网络' => array(),
939
+ '组織' => array(),
940
+ '網絡' => array(),
941
+ '网絡' => array(),
942
+ '组织' => array(),
943
+ '組織' => array(),
944
+ '組织' => array(),
945
+ 'blogspot' => array()),
946
+ 'hm' => array(),
947
+ 'hn' => array('com' => array(),
948
+ 'edu' => array(),
949
+ 'org' => array(),
950
+ 'net' => array(),
951
+ 'mil' => array(),
952
+ 'gob' => array()),
953
+ 'hr' => array('iz' => array(),
954
+ 'from' => array(),
955
+ 'name' => array(),
956
+ 'com' => array()),
957
+ 'ht' => array('com' => array(),
958
+ 'shop' => array(),
959
+ 'firm' => array(),
960
+ 'info' => array(),
961
+ 'adult' => array(),
962
+ 'net' => array(),
963
+ 'pro' => array(),
964
+ 'org' => array(),
965
+ 'med' => array(),
966
+ 'art' => array(),
967
+ 'coop' => array(),
968
+ 'pol' => array(),
969
+ 'asso' => array(),
970
+ 'edu' => array(),
971
+ 'rel' => array(),
972
+ 'gouv' => array(),
973
+ 'perso' => array()),
974
+ 'hu' => array('co' => array(),
975
+ 'info' => array(),
976
+ 'org' => array(),
977
+ 'priv' => array(),
978
+ 'sport' => array(),
979
+ 'tm' => array(),
980
+ '2000' => array(),
981
+ 'agrar' => array(),
982
+ 'bolt' => array(),
983
+ 'casino' => array(),
984
+ 'city' => array(),
985
+ 'erotica' => array(),
986
+ 'erotika' => array(),
987
+ 'film' => array(),
988
+ 'forum' => array(),
989
+ 'games' => array(),
990
+ 'hotel' => array(),
991
+ 'ingatlan' => array(),
992
+ 'jogasz' => array(),
993
+ 'konyvelo' => array(),
994
+ 'lakas' => array(),
995
+ 'media' => array(),
996
+ 'news' => array(),
997
+ 'reklam' => array(),
998
+ 'sex' => array(),
999
+ 'shop' => array(),
1000
+ 'suli' => array(),
1001
+ 'szex' => array(),
1002
+ 'tozsde' => array(),
1003
+ 'utazas' => array(),
1004
+ 'video' => array(),
1005
+ 'blogspot' => array()),
1006
+ 'id' => array('ac' => array(),
1007
+ 'biz' => array(),
1008
+ 'co' => array(),
1009
+ 'desa' => array(),
1010
+ 'go' => array(),
1011
+ 'mil' => array(),
1012
+ 'my' => array(),
1013
+ 'net' => array(),
1014
+ 'or' => array(),
1015
+ 'sch' => array(),
1016
+ 'web' => array()),
1017
+ 'ie' => array('gov' => array(),
1018
+ 'blogspot' => array()),
1019
+ 'il' => array('*' => array(),
1020
+ 'co' => array('blogspot' => array())),
1021
+ 'im' => array('ac' => array(),
1022
+ 'co' => array('ltd' => array(),
1023
+ 'plc' => array()),
1024
+ 'com' => array(),
1025
+ 'net' => array(),
1026
+ 'org' => array(),
1027
+ 'tt' => array(),
1028
+ 'tv' => array()),
1029
+ 'in' => array('co' => array(),
1030
+ 'firm' => array(),
1031
+ 'net' => array(),
1032
+ 'org' => array(),
1033
+ 'gen' => array(),
1034
+ 'ind' => array(),
1035
+ 'nic' => array(),
1036
+ 'ac' => array(),
1037
+ 'edu' => array(),
1038
+ 'res' => array(),
1039
+ 'gov' => array(),
1040
+ 'mil' => array(),
1041
+ 'blogspot' => array()),
1042
+ 'info' => array('dyndns' => array(),
1043
+ 'barrel-of-knowledge' => array(),
1044
+ 'barrell-of-knowledge' => array(),
1045
+ 'for-our' => array(),
1046
+ 'groks-the' => array(),
1047
+ 'groks-this' => array(),
1048
+ 'here-for-more' => array(),
1049
+ 'knowsitall' => array(),
1050
+ 'selfip' => array(),
1051
+ 'webhop' => array()),
1052
+ 'int' => array('eu' => array()),
1053
+ 'io' => array('com' => array(),
1054
+ 'github' => array(),
1055
+ 'nid' => array()),
1056
+ 'iq' => array('gov' => array(),
1057
+ 'edu' => array(),
1058
+ 'mil' => array(),
1059
+ 'com' => array(),
1060
+ 'org' => array(),
1061
+ 'net' => array()),
1062
+ 'ir' => array('ac' => array(),
1063
+ 'co' => array(),
1064
+ 'gov' => array(),
1065
+ 'id' => array(),
1066
+ 'net' => array(),
1067
+ 'org' => array(),
1068
+ 'sch' => array(),
1069
+ 'ایران' => array(),
1070
+ 'ايران' => array()),
1071
+ 'is' => array('net' => array(),
1072
+ 'com' => array(),
1073
+ 'edu' => array(),
1074
+ 'gov' => array(),
1075
+ 'org' => array(),
1076
+ 'int' => array(),
1077
+ 'cupcake' => array()),
1078
+ 'it' => array('gov' => array(),
1079
+ 'edu' => array(),
1080
+ 'abr' => array(),
1081
+ 'abruzzo' => array(),
1082
+ 'aosta-valley' => array(),
1083
+ 'aostavalley' => array(),
1084
+ 'bas' => array(),
1085
+ 'basilicata' => array(),
1086
+ 'cal' => array(),
1087
+ 'calabria' => array(),
1088
+ 'cam' => array(),
1089
+ 'campania' => array(),
1090
+ 'emilia-romagna' => array(),
1091
+ 'emiliaromagna' => array(),
1092
+ 'emr' => array(),
1093
+ 'friuli-v-giulia' => array(),
1094
+ 'friuli-ve-giulia' => array(),
1095
+ 'friuli-vegiulia' => array(),
1096
+ 'friuli-venezia-giulia' => array(),
1097
+ 'friuli-veneziagiulia' => array(),
1098
+ 'friuli-vgiulia' => array(),
1099
+ 'friuliv-giulia' => array(),
1100
+ 'friulive-giulia' => array(),
1101
+ 'friulivegiulia' => array(),
1102
+ 'friulivenezia-giulia' => array(),
1103
+ 'friuliveneziagiulia' => array(),
1104
+ 'friulivgiulia' => array(),
1105
+ 'fvg' => array(),
1106
+ 'laz' => array(),
1107
+ 'lazio' => array(),
1108
+ 'lig' => array(),
1109
+ 'liguria' => array(),
1110
+ 'lom' => array(),
1111
+ 'lombardia' => array(),
1112
+ 'lombardy' => array(),
1113
+ 'lucania' => array(),
1114
+ 'mar' => array(),
1115
+ 'marche' => array(),
1116
+ 'mol' => array(),
1117
+ 'molise' => array(),
1118
+ 'piedmont' => array(),
1119
+ 'piemonte' => array(),
1120
+ 'pmn' => array(),
1121
+ 'pug' => array(),
1122
+ 'puglia' => array(),
1123
+ 'sar' => array(),
1124
+ 'sardegna' => array(),
1125
+ 'sardinia' => array(),
1126
+ 'sic' => array(),
1127
+ 'sicilia' => array(),
1128
+ 'sicily' => array(),
1129
+ 'taa' => array(),
1130
+ 'tos' => array(),
1131
+ 'toscana' => array(),
1132
+ 'trentino-a-adige' => array(),
1133
+ 'trentino-aadige' => array(),
1134
+ 'trentino-alto-adige' => array(),
1135
+ 'trentino-altoadige' => array(),
1136
+ 'trentino-s-tirol' => array(),
1137
+ 'trentino-stirol' => array(),
1138
+ 'trentino-sud-tirol' => array(),
1139
+ 'trentino-sudtirol' => array(),
1140
+ 'trentino-sued-tirol' => array(),
1141
+ 'trentino-suedtirol' => array(),
1142
+ 'trentinoa-adige' => array(),
1143
+ 'trentinoaadige' => array(),
1144
+ 'trentinoalto-adige' => array(),
1145
+ 'trentinoaltoadige' => array(),
1146
+ 'trentinos-tirol' => array(),
1147
+ 'trentinostirol' => array(),
1148
+ 'trentinosud-tirol' => array(),
1149
+ 'trentinosudtirol' => array(),
1150
+ 'trentinosued-tirol' => array(),
1151
+ 'trentinosuedtirol' => array(),
1152
+ 'tuscany' => array(),
1153
+ 'umb' => array(),
1154
+ 'umbria' => array(),
1155
+ 'val-d-aosta' => array(),
1156
+ 'val-daosta' => array(),
1157
+ 'vald-aosta' => array(),
1158
+ 'valdaosta' => array(),
1159
+ 'valle-aosta' => array(),
1160
+ 'valle-d-aosta' => array(),
1161
+ 'valle-daosta' => array(),
1162
+ 'valleaosta' => array(),
1163
+ 'valled-aosta' => array(),
1164
+ 'valledaosta' => array(),
1165
+ 'vallee-aoste' => array(),
1166
+ 'valleeaoste' => array(),
1167
+ 'vao' => array(),
1168
+ 'vda' => array(),
1169
+ 'ven' => array(),
1170
+ 'veneto' => array(),
1171
+ 'ag' => array(),
1172
+ 'agrigento' => array(),
1173
+ 'al' => array(),
1174
+ 'alessandria' => array(),
1175
+ 'alto-adige' => array(),
1176
+ 'altoadige' => array(),
1177
+ 'an' => array(),
1178
+ 'ancona' => array(),
1179
+ 'andria-barletta-trani' => array(),
1180
+ 'andria-trani-barletta' => array(),
1181
+ 'andriabarlettatrani' => array(),
1182
+ 'andriatranibarletta' => array(),
1183
+ 'ao' => array(),
1184
+ 'aosta' => array(),
1185
+ 'aoste' => array(),
1186
+ 'ap' => array(),
1187
+ 'aq' => array(),
1188
+ 'aquila' => array(),
1189
+ 'ar' => array(),
1190
+ 'arezzo' => array(),
1191
+ 'ascoli-piceno' => array(),
1192
+ 'ascolipiceno' => array(),
1193
+ 'asti' => array(),
1194
+ 'at' => array(),
1195
+ 'av' => array(),
1196
+ 'avellino' => array(),
1197
+ 'ba' => array(),
1198
+ 'balsan' => array(),
1199
+ 'bari' => array(),
1200
+ 'barletta-trani-andria' => array(),
1201
+ 'barlettatraniandria' => array(),
1202
+ 'belluno' => array(),
1203
+ 'benevento' => array(),
1204
+ 'bergamo' => array(),
1205
+ 'bg' => array(),
1206
+ 'bi' => array(),
1207
+ 'biella' => array(),
1208
+ 'bl' => array(),
1209
+ 'bn' => array(),
1210
+ 'bo' => array(),
1211
+ 'bologna' => array(),
1212
+ 'bolzano' => array(),
1213
+ 'bozen' => array(),
1214
+ 'br' => array(),
1215
+ 'brescia' => array(),
1216
+ 'brindisi' => array(),
1217
+ 'bs' => array(),
1218
+ 'bt' => array(),
1219
+ 'bz' => array(),
1220
+ 'ca' => array(),
1221
+ 'cagliari' => array(),
1222
+ 'caltanissetta' => array(),
1223
+ 'campidano-medio' => array(),
1224
+ 'campidanomedio' => array(),
1225
+ 'campobasso' => array(),
1226
+ 'carbonia-iglesias' => array(),
1227
+ 'carboniaiglesias' => array(),
1228
+ 'carrara-massa' => array(),
1229
+ 'carraramassa' => array(),
1230
+ 'caserta' => array(),
1231
+ 'catania' => array(),
1232
+ 'catanzaro' => array(),
1233
+ 'cb' => array(),
1234
+ 'ce' => array(),
1235
+ 'cesena-forli' => array(),
1236
+ 'cesenaforli' => array(),
1237
+ 'ch' => array(),
1238
+ 'chieti' => array(),
1239
+ 'ci' => array(),
1240
+ 'cl' => array(),
1241
+ 'cn' => array(),
1242
+ 'co' => array(),
1243
+ 'como' => array(),
1244
+ 'cosenza' => array(),
1245
+ 'cr' => array(),
1246
+ 'cremona' => array(),
1247
+ 'crotone' => array(),
1248
+ 'cs' => array(),
1249
+ 'ct' => array(),
1250
+ 'cuneo' => array(),
1251
+ 'cz' => array(),
1252
+ 'dell-ogliastra' => array(),
1253
+ 'dellogliastra' => array(),
1254
+ 'en' => array(),
1255
+ 'enna' => array(),
1256
+ 'fc' => array(),
1257
+ 'fe' => array(),
1258
+ 'fermo' => array(),
1259
+ 'ferrara' => array(),
1260
+ 'fg' => array(),
1261
+ 'fi' => array(),
1262
+ 'firenze' => array(),
1263
+ 'florence' => array(),
1264
+ 'fm' => array(),
1265
+ 'foggia' => array(),
1266
+ 'forli-cesena' => array(),
1267
+ 'forlicesena' => array(),
1268
+ 'fr' => array(),
1269
+ 'frosinone' => array(),
1270
+ 'ge' => array(),
1271
+ 'genoa' => array(),
1272
+ 'genova' => array(),
1273
+ 'go' => array(),
1274
+ 'gorizia' => array(),
1275
+ 'gr' => array(),
1276
+ 'grosseto' => array(),
1277
+ 'iglesias-carbonia' => array(),
1278
+ 'iglesiascarbonia' => array(),
1279
+ 'im' => array(),
1280
+ 'imperia' => array(),
1281
+ 'is' => array(),
1282
+ 'isernia' => array(),
1283
+ 'kr' => array(),
1284
+ 'la-spezia' => array(),
1285
+ 'laquila' => array(),
1286
+ 'laspezia' => array(),
1287
+ 'latina' => array(),
1288
+ 'lc' => array(),
1289
+ 'le' => array(),
1290
+ 'lecce' => array(),
1291
+ 'lecco' => array(),
1292
+ 'li' => array(),
1293
+ 'livorno' => array(),
1294
+ 'lo' => array(),
1295
+ 'lodi' => array(),
1296
+ 'lt' => array(),
1297
+ 'lu' => array(),
1298
+ 'lucca' => array(),
1299
+ 'macerata' => array(),
1300
+ 'mantova' => array(),
1301
+ 'massa-carrara' => array(),
1302
+ 'massacarrara' => array(),
1303
+ 'matera' => array(),
1304
+ 'mb' => array(),
1305
+ 'mc' => array(),
1306
+ 'me' => array(),
1307
+ 'medio-campidano' => array(),
1308
+ 'mediocampidano' => array(),
1309
+ 'messina' => array(),
1310
+ 'mi' => array(),
1311
+ 'milan' => array(),
1312
+ 'milano' => array(),
1313
+ 'mn' => array(),
1314
+ 'mo' => array(),
1315
+ 'modena' => array(),
1316
+ 'monza-brianza' => array(),
1317
+ 'monza-e-della-brianza' => array(),
1318
+ 'monza' => array(),
1319
+ 'monzabrianza' => array(),
1320
+ 'monzaebrianza' => array(),
1321
+ 'monzaedellabrianza' => array(),
1322
+ 'ms' => array(),
1323
+ 'mt' => array(),
1324
+ 'na' => array(),
1325
+ 'naples' => array(),
1326
+ 'napoli' => array(),
1327
+ 'no' => array(),
1328
+ 'novara' => array(),
1329
+ 'nu' => array(),
1330
+ 'nuoro' => array(),
1331
+ 'og' => array(),
1332
+ 'ogliastra' => array(),
1333
+ 'olbia-tempio' => array(),
1334
+ 'olbiatempio' => array(),
1335
+ 'or' => array(),
1336
+ 'oristano' => array(),
1337
+ 'ot' => array(),
1338
+ 'pa' => array(),
1339
+ 'padova' => array(),
1340
+ 'padua' => array(),
1341
+ 'palermo' => array(),
1342
+ 'parma' => array(),
1343
+ 'pavia' => array(),
1344
+ 'pc' => array(),
1345
+ 'pd' => array(),
1346
+ 'pe' => array(),
1347
+ 'perugia' => array(),
1348
+ 'pesaro-urbino' => array(),
1349
+ 'pesarourbino' => array(),
1350
+ 'pescara' => array(),
1351
+ 'pg' => array(),
1352
+ 'pi' => array(),
1353
+ 'piacenza' => array(),
1354
+ 'pisa' => array(),
1355
+ 'pistoia' => array(),
1356
+ 'pn' => array(),
1357
+ 'po' => array(),
1358
+ 'pordenone' => array(),
1359
+ 'potenza' => array(),
1360
+ 'pr' => array(),
1361
+ 'prato' => array(),
1362
+ 'pt' => array(),
1363
+ 'pu' => array(),
1364
+ 'pv' => array(),
1365
+ 'pz' => array(),
1366
+ 'ra' => array(),
1367
+ 'ragusa' => array(),
1368
+ 'ravenna' => array(),
1369
+ 'rc' => array(),
1370
+ 're' => array(),
1371
+ 'reggio-calabria' => array(),
1372
+ 'reggio-emilia' => array(),
1373
+ 'reggiocalabria' => array(),
1374
+ 'reggioemilia' => array(),
1375
+ 'rg' => array(),
1376
+ 'ri' => array(),
1377
+ 'rieti' => array(),
1378
+ 'rimini' => array(),
1379
+ 'rm' => array(),
1380
+ 'rn' => array(),
1381
+ 'ro' => array(),
1382
+ 'roma' => array(),
1383
+ 'rome' => array(),
1384
+ 'rovigo' => array(),
1385
+ 'sa' => array(),
1386
+ 'salerno' => array(),
1387
+ 'sassari' => array(),
1388
+ 'savona' => array(),
1389
+ 'si' => array(),
1390
+ 'siena' => array(),
1391
+ 'siracusa' => array(),
1392
+ 'so' => array(),
1393
+ 'sondrio' => array(),
1394
+ 'sp' => array(),
1395
+ 'sr' => array(),
1396
+ 'ss' => array(),
1397
+ 'suedtirol' => array(),
1398
+ 'sv' => array(),
1399
+ 'ta' => array(),
1400
+ 'taranto' => array(),
1401
+ 'te' => array(),
1402
+ 'tempio-olbia' => array(),
1403
+ 'tempioolbia' => array(),
1404
+ 'teramo' => array(),
1405
+ 'terni' => array(),
1406
+ 'tn' => array(),
1407
+ 'to' => array(),
1408
+ 'torino' => array(),
1409
+ 'tp' => array(),
1410
+ 'tr' => array(),
1411
+ 'trani-andria-barletta' => array(),
1412
+ 'trani-barletta-andria' => array(),
1413
+ 'traniandriabarletta' => array(),
1414
+ 'tranibarlettaandria' => array(),
1415
+ 'trapani' => array(),
1416
+ 'trentino' => array(),
1417
+ 'trento' => array(),
1418
+ 'treviso' => array(),
1419
+ 'trieste' => array(),
1420
+ 'ts' => array(),
1421
+ 'turin' => array(),
1422
+ 'tv' => array(),
1423
+ 'ud' => array(),
1424
+ 'udine' => array(),
1425
+ 'urbino-pesaro' => array(),
1426
+ 'urbinopesaro' => array(),
1427
+ 'va' => array(),
1428
+ 'varese' => array(),
1429
+ 'vb' => array(),
1430
+ 'vc' => array(),
1431
+ 've' => array(),
1432
+ 'venezia' => array(),
1433
+ 'venice' => array(),
1434
+ 'verbania' => array(),
1435
+ 'vercelli' => array(),
1436
+ 'verona' => array(),
1437
+ 'vi' => array(),
1438
+ 'vibo-valentia' => array(),
1439
+ 'vibovalentia' => array(),
1440
+ 'vicenza' => array(),
1441
+ 'viterbo' => array(),
1442
+ 'vr' => array(),
1443
+ 'vs' => array(),
1444
+ 'vt' => array(),
1445
+ 'vv' => array(),
1446
+ 'blogspot' => array()),
1447
+ 'je' => array('co' => array(),
1448
+ 'net' => array(),
1449
+ 'org' => array()),
1450
+ 'jm' => array('*' => array()),
1451
+ 'jo' => array('com' => array(),
1452
+ 'org' => array(),
1453
+ 'net' => array(),
1454
+ 'edu' => array(),
1455
+ 'sch' => array(),
1456
+ 'gov' => array(),
1457
+ 'mil' => array(),
1458
+ 'name' => array()),
1459
+ 'jobs' => array(),
1460
+ 'jp' => array('ac' => array(),
1461
+ 'ad' => array(),
1462
+ 'co' => array(),
1463
+ 'ed' => array(),
1464
+ 'go' => array(),
1465
+ 'gr' => array(),
1466
+ 'lg' => array(),
1467
+ 'ne' => array(),
1468
+ 'or' => array(),
1469
+ 'aichi' => array('aisai' => array(),
1470
+ 'ama' => array(),
1471
+ 'anjo' => array(),
1472
+ 'asuke' => array(),
1473
+ 'chiryu' => array(),
1474
+ 'chita' => array(),
1475
+ 'fuso' => array(),
1476
+ 'gamagori' => array(),
1477
+ 'handa' => array(),
1478
+ 'hazu' => array(),
1479
+ 'hekinan' => array(),
1480
+ 'higashiura' => array(),
1481
+ 'ichinomiya' => array(),
1482
+ 'inazawa' => array(),
1483
+ 'inuyama' => array(),
1484
+ 'isshiki' => array(),
1485
+ 'iwakura' => array(),
1486
+ 'kanie' => array(),
1487
+ 'kariya' => array(),
1488
+ 'kasugai' => array(),
1489
+ 'kira' => array(),
1490
+ 'kiyosu' => array(),
1491
+ 'komaki' => array(),
1492
+ 'konan' => array(),
1493
+ 'kota' => array(),
1494
+ 'mihama' => array(),
1495
+ 'miyoshi' => array(),
1496
+ 'nishio' => array(),
1497
+ 'nisshin' => array(),
1498
+ 'obu' => array(),
1499
+ 'oguchi' => array(),
1500
+ 'oharu' => array(),
1501
+ 'okazaki' => array(),
1502
+ 'owariasahi' => array(),
1503
+ 'seto' => array(),
1504
+ 'shikatsu' => array(),
1505
+ 'shinshiro' => array(),
1506
+ 'shitara' => array(),
1507
+ 'tahara' => array(),
1508
+ 'takahama' => array(),
1509
+ 'tobishima' => array(),
1510
+ 'toei' => array(),
1511
+ 'togo' => array(),
1512
+ 'tokai' => array(),
1513
+ 'tokoname' => array(),
1514
+ 'toyoake' => array(),
1515
+ 'toyohashi' => array(),
1516
+ 'toyokawa' => array(),
1517
+ 'toyone' => array(),
1518
+ 'toyota' => array(),
1519
+ 'tsushima' => array(),
1520
+ 'yatomi' => array()),
1521
+ 'akita' => array('akita' => array(),
1522
+ 'daisen' => array(),
1523
+ 'fujisato' => array(),
1524
+ 'gojome' => array(),
1525
+ 'hachirogata' => array(),
1526
+ 'happou' => array(),
1527
+ 'higashinaruse' => array(),
1528
+ 'honjo' => array(),
1529
+ 'honjyo' => array(),
1530
+ 'ikawa' => array(),
1531
+ 'kamikoani' => array(),
1532
+ 'kamioka' => array(),
1533
+ 'katagami' => array(),
1534
+ 'kazuno' => array(),
1535
+ 'kitaakita' => array(),
1536
+ 'kosaka' => array(),
1537
+ 'kyowa' => array(),
1538
+ 'misato' => array(),
1539
+ 'mitane' => array(),
1540
+ 'moriyoshi' => array(),
1541
+ 'nikaho' => array(),
1542
+ 'noshiro' => array(),
1543
+ 'odate' => array(),
1544
+ 'oga' => array(),
1545
+ 'ogata' => array(),
1546
+ 'semboku' => array(),
1547
+ 'yokote' => array(),
1548
+ 'yurihonjo' => array()),
1549
+ 'aomori' => array('aomori' => array(),
1550
+ 'gonohe' => array(),
1551
+ 'hachinohe' => array(),
1552
+ 'hashikami' => array(),
1553
+ 'hiranai' => array(),
1554
+ 'hirosaki' => array(),
1555
+ 'itayanagi' => array(),
1556
+ 'kuroishi' => array(),
1557
+ 'misawa' => array(),
1558
+ 'mutsu' => array(),
1559
+ 'nakadomari' => array(),
1560
+ 'noheji' => array(),
1561
+ 'oirase' => array(),
1562
+ 'owani' => array(),
1563
+ 'rokunohe' => array(),
1564
+ 'sannohe' => array(),
1565
+ 'shichinohe' => array(),
1566
+ 'shingo' => array(),
1567
+ 'takko' => array(),
1568
+ 'towada' => array(),
1569
+ 'tsugaru' => array(),
1570
+ 'tsuruta' => array()),
1571
+ 'chiba' => array('abiko' => array(),
1572
+ 'asahi' => array(),
1573
+ 'chonan' => array(),
1574
+ 'chosei' => array(),
1575
+ 'choshi' => array(),
1576
+ 'chuo' => array(),
1577
+ 'funabashi' => array(),
1578
+ 'futtsu' => array(),
1579
+ 'hanamigawa' => array(),
1580
+ 'ichihara' => array(),
1581
+ 'ichikawa' => array(),
1582
+ 'ichinomiya' => array(),
1583
+ 'inzai' => array(),
1584
+ 'isumi' => array(),
1585
+ 'kamagaya' => array(),
1586
+ 'kamogawa' => array(),
1587
+ 'kashiwa' => array(),
1588
+ 'katori' => array(),
1589
+ 'katsuura' => array(),
1590
+ 'kimitsu' => array(),
1591
+ 'kisarazu' => array(),
1592
+ 'kozaki' => array(),
1593
+ 'kujukuri' => array(),
1594
+ 'kyonan' => array(),
1595
+ 'matsudo' => array(),
1596
+ 'midori' => array(),
1597
+ 'mihama' => array(),
1598
+ 'minamiboso' => array(),
1599
+ 'mobara' => array(),
1600
+ 'mutsuzawa' => array(),
1601
+ 'nagara' => array(),
1602
+ 'nagareyama' => array(),
1603
+ 'narashino' => array(),
1604
+ 'narita' => array(),
1605
+ 'noda' => array(),
1606
+ 'oamishirasato' => array(),
1607
+ 'omigawa' => array(),
1608
+ 'onjuku' => array(),
1609
+ 'otaki' => array(),
1610
+ 'sakae' => array(),
1611
+ 'sakura' => array(),
1612
+ 'shimofusa' => array(),
1613
+ 'shirako' => array(),
1614
+ 'shiroi' => array(),
1615
+ 'shisui' => array(),
1616
+ 'sodegaura' => array(),
1617
+ 'sosa' => array(),
1618
+ 'tako' => array(),
1619
+ 'tateyama' => array(),
1620
+ 'togane' => array(),
1621
+ 'tohnosho' => array(),
1622
+ 'tomisato' => array(),
1623
+ 'urayasu' => array(),
1624
+ 'yachimata' => array(),
1625
+ 'yachiyo' => array(),
1626
+ 'yokaichiba' => array(),
1627
+ 'yokoshibahikari' => array(),
1628
+ 'yotsukaido' => array()),
1629
+ 'ehime' => array('ainan' => array(),
1630
+ 'honai' => array(),
1631
+ 'ikata' => array(),
1632
+ 'imabari' => array(),
1633
+ 'iyo' => array(),
1634
+ 'kamijima' => array(),
1635
+ 'kihoku' => array(),
1636
+ 'kumakogen' => array(),
1637
+ 'masaki' => array(),
1638
+ 'matsuno' => array(),
1639
+ 'matsuyama' => array(),
1640
+ 'namikata' => array(),
1641
+ 'niihama' => array(),
1642
+ 'ozu' => array(),
1643
+ 'saijo' => array(),
1644
+ 'seiyo' => array(),
1645
+ 'shikokuchuo' => array(),
1646
+ 'tobe' => array(),
1647
+ 'toon' => array(),
1648
+ 'uchiko' => array(),
1649
+ 'uwajima' => array(),
1650
+ 'yawatahama' => array()),
1651
+ 'fukui' => array('echizen' => array(),
1652
+ 'eiheiji' => array(),
1653
+ 'fukui' => array(),
1654
+ 'ikeda' => array(),
1655
+ 'katsuyama' => array(),
1656
+ 'mihama' => array(),
1657
+ 'minamiechizen' => array(),
1658
+ 'obama' => array(),
1659
+ 'ohi' => array(),
1660
+ 'ono' => array(),
1661
+ 'sabae' => array(),
1662
+ 'sakai' => array(),
1663
+ 'takahama' => array(),
1664
+ 'tsuruga' => array(),
1665
+ 'wakasa' => array()),
1666
+ 'fukuoka' => array('ashiya' => array(),
1667
+ 'buzen' => array(),
1668
+ 'chikugo' => array(),
1669
+ 'chikuho' => array(),
1670
+ 'chikujo' => array(),
1671
+ 'chikushino' => array(),
1672
+ 'chikuzen' => array(),
1673
+ 'chuo' => array(),
1674
+ 'dazaifu' => array(),
1675
+ 'fukuchi' => array(),
1676
+ 'hakata' => array(),
1677
+ 'higashi' => array(),
1678
+ 'hirokawa' => array(),
1679
+ 'hisayama' => array(),
1680
+ 'iizuka' => array(),
1681
+ 'inatsuki' => array(),
1682
+ 'kaho' => array(),
1683
+ 'kasuga' => array(),
1684
+ 'kasuya' => array(),
1685
+ 'kawara' => array(),
1686
+ 'keisen' => array(),
1687
+ 'koga' => array(),
1688
+ 'kurate' => array(),
1689
+ 'kurogi' => array(),
1690
+ 'kurume' => array(),
1691
+ 'minami' => array(),
1692
+ 'miyako' => array(),
1693
+ 'miyama' => array(),
1694
+ 'miyawaka' => array(),
1695
+ 'mizumaki' => array(),
1696
+ 'munakata' => array(),
1697
+ 'nakagawa' => array(),
1698
+ 'nakama' => array(),
1699
+ 'nishi' => array(),
1700
+ 'nogata' => array(),
1701
+ 'ogori' => array(),
1702
+ 'okagaki' => array(),
1703
+ 'okawa' => array(),
1704
+ 'oki' => array(),
1705
+ 'omuta' => array(),
1706
+ 'onga' => array(),
1707
+ 'onojo' => array(),
1708
+ 'oto' => array(),
1709
+ 'saigawa' => array(),
1710
+ 'sasaguri' => array(),
1711
+ 'shingu' => array(),
1712
+ 'shinyoshitomi' => array(),
1713
+ 'shonai' => array(),
1714
+ 'soeda' => array(),
1715
+ 'sue' => array(),
1716
+ 'tachiarai' => array(),
1717
+ 'tagawa' => array(),
1718
+ 'takata' => array(),
1719
+ 'toho' => array(),
1720
+ 'toyotsu' => array(),
1721
+ 'tsuiki' => array(),
1722
+ 'ukiha' => array(),
1723
+ 'umi' => array(),
1724
+ 'usui' => array(),
1725
+ 'yamada' => array(),
1726
+ 'yame' => array(),
1727
+ 'yanagawa' => array(),
1728
+ 'yukuhashi' => array()),
1729
+ 'fukushima' => array('aizubange' => array(),
1730
+ 'aizumisato' => array(),
1731
+ 'aizuwakamatsu' => array(),
1732
+ 'asakawa' => array(),
1733
+ 'bandai' => array(),
1734
+ 'date' => array(),
1735
+ 'fukushima' => array(),
1736
+ 'furudono' => array(),
1737
+ 'futaba' => array(),
1738
+ 'hanawa' => array(),
1739
+ 'higashi' => array(),
1740
+ 'hirata' => array(),
1741
+ 'hirono' => array(),
1742
+ 'iitate' => array(),
1743
+ 'inawashiro' => array(),
1744
+ 'ishikawa' => array(),
1745
+ 'iwaki' => array(),
1746
+ 'izumizaki' => array(),
1747
+ 'kagamiishi' => array(),
1748
+ 'kaneyama' => array(),
1749
+ 'kawamata' => array(),
1750
+ 'kitakata' => array(),
1751
+ 'kitashiobara' => array(),
1752
+ 'koori' => array(),
1753
+ 'koriyama' => array(),
1754
+ 'kunimi' => array(),
1755
+ 'miharu' => array(),
1756
+ 'mishima' => array(),
1757
+ 'namie' => array(),
1758
+ 'nango' => array(),
1759
+ 'nishiaizu' => array(),
1760
+ 'nishigo' => array(),
1761
+ 'okuma' => array(),
1762
+ 'omotego' => array(),
1763
+ 'ono' => array(),
1764
+ 'otama' => array(),
1765
+ 'samegawa' => array(),
1766
+ 'shimogo' => array(),
1767
+ 'shirakawa' => array(),
1768
+ 'showa' => array(),
1769
+ 'soma' => array(),
1770
+ 'sukagawa' => array(),
1771
+ 'taishin' => array(),
1772
+ 'tamakawa' => array(),
1773
+ 'tanagura' => array(),
1774
+ 'tenei' => array(),
1775
+ 'yabuki' => array(),
1776
+ 'yamato' => array(),
1777
+ 'yamatsuri' => array(),
1778
+ 'yanaizu' => array(),
1779
+ 'yugawa' => array()),
1780
+ 'gifu' => array('anpachi' => array(),
1781
+ 'ena' => array(),
1782
+ 'gifu' => array(),
1783
+ 'ginan' => array(),
1784
+ 'godo' => array(),
1785
+ 'gujo' => array(),
1786
+ 'hashima' => array(),
1787
+ 'hichiso' => array(),
1788
+ 'hida' => array(),
1789
+ 'higashishirakawa' => array(),
1790
+ 'ibigawa' => array(),
1791
+ 'ikeda' => array(),
1792
+ 'kakamigahara' => array(),
1793
+ 'kani' => array(),
1794
+ 'kasahara' => array(),
1795
+ 'kasamatsu' => array(),
1796
+ 'kawaue' => array(),
1797
+ 'kitagata' => array(),
1798
+ 'mino' => array(),
1799
+ 'minokamo' => array(),
1800
+ 'mitake' => array(),
1801
+ 'mizunami' => array(),
1802
+ 'motosu' => array(),
1803
+ 'nakatsugawa' => array(),
1804
+ 'ogaki' => array(),
1805
+ 'sakahogi' => array(),
1806
+ 'seki' => array(),
1807
+ 'sekigahara' => array(),
1808
+ 'shirakawa' => array(),
1809
+ 'tajimi' => array(),
1810
+ 'takayama' => array(),
1811
+ 'tarui' => array(),
1812
+ 'toki' => array(),
1813
+ 'tomika' => array(),
1814
+ 'wanouchi' => array(),
1815
+ 'yamagata' => array(),
1816
+ 'yaotsu' => array(),
1817
+ 'yoro' => array()),
1818
+ 'gunma' => array('annaka' => array(),
1819
+ 'chiyoda' => array(),
1820
+ 'fujioka' => array(),
1821
+ 'higashiagatsuma' => array(),
1822
+ 'isesaki' => array(),
1823
+ 'itakura' => array(),
1824
+ 'kanna' => array(),
1825
+ 'kanra' => array(),
1826
+ 'katashina' => array(),
1827
+ 'kawaba' => array(),
1828
+ 'kiryu' => array(),
1829
+ 'kusatsu' => array(),
1830
+ 'maebashi' => array(),
1831
+ 'meiwa' => array(),
1832
+ 'midori' => array(),
1833
+ 'minakami' => array(),
1834
+ 'naganohara' => array(),
1835
+ 'nakanojo' => array(),
1836
+ 'nanmoku' => array(),
1837
+ 'numata' => array(),
1838
+ 'oizumi' => array(),
1839
+ 'ora' => array(),
1840
+ 'ota' => array(),
1841
+ 'shibukawa' => array(),
1842
+ 'shimonita' => array(),
1843
+ 'shinto' => array(),
1844
+ 'showa' => array(),
1845
+ 'takasaki' => array(),
1846
+ 'takayama' => array(),
1847
+ 'tamamura' => array(),
1848
+ 'tatebayashi' => array(),
1849
+ 'tomioka' => array(),
1850
+ 'tsukiyono' => array(),
1851
+ 'tsumagoi' => array(),
1852
+ 'ueno' => array(),
1853
+ 'yoshioka' => array()),
1854
+ 'hiroshima' => array('asaminami' => array(),
1855
+ 'daiwa' => array(),
1856
+ 'etajima' => array(),
1857
+ 'fuchu' => array(),
1858
+ 'fukuyama' => array(),
1859
+ 'hatsukaichi' => array(),
1860
+ 'higashihiroshima' => array(),
1861
+ 'hongo' => array(),
1862
+ 'jinsekikogen' => array(),
1863
+ 'kaita' => array(),
1864
+ 'kui' => array(),
1865
+ 'kumano' => array(),
1866
+ 'kure' => array(),
1867
+ 'mihara' => array(),
1868
+ 'miyoshi' => array(),
1869
+ 'naka' => array(),
1870
+ 'onomichi' => array(),
1871
+ 'osakikamijima' => array(),
1872
+ 'otake' => array(),
1873
+ 'saka' => array(),
1874
+ 'sera' => array(),
1875
+ 'seranishi' => array(),
1876
+ 'shinichi' => array(),
1877
+ 'shobara' => array(),
1878
+ 'takehara' => array()),
1879
+ 'hokkaido' => array('abashiri' => array(),
1880
+ 'abira' => array(),
1881
+ 'aibetsu' => array(),
1882
+ 'akabira' => array(),
1883
+ 'akkeshi' => array(),
1884
+ 'asahikawa' => array(),
1885
+ 'ashibetsu' => array(),
1886
+ 'ashoro' => array(),
1887
+ 'assabu' => array(),
1888
+ 'atsuma' => array(),
1889
+ 'bibai' => array(),
1890
+ 'biei' => array(),
1891
+ 'bifuka' => array(),
1892
+ 'bihoro' => array(),
1893
+ 'biratori' => array(),
1894
+ 'chippubetsu' => array(),
1895
+ 'chitose' => array(),
1896
+ 'date' => array(),
1897
+ 'ebetsu' => array(),
1898
+ 'embetsu' => array(),
1899
+ 'eniwa' => array(),
1900
+ 'erimo' => array(),
1901
+ 'esan' => array(),
1902
+ 'esashi' => array(),
1903
+ 'fukagawa' => array(),
1904
+ 'fukushima' => array(),
1905
+ 'furano' => array(),
1906
+ 'furubira' => array(),
1907
+ 'haboro' => array(),
1908
+ 'hakodate' => array(),
1909
+ 'hamatonbetsu' => array(),
1910
+ 'hidaka' => array(),
1911
+ 'higashikagura' => array(),
1912
+ 'higashikawa' => array(),
1913
+ 'hiroo' => array(),
1914
+ 'hokuryu' => array(),
1915
+ 'hokuto' => array(),
1916
+ 'honbetsu' => array(),
1917
+ 'horokanai' => array(),
1918
+ 'horonobe' => array(),
1919
+ 'ikeda' => array(),
1920
+ 'imakane' => array(),
1921
+ 'ishikari' => array(),
1922
+ 'iwamizawa' => array(),
1923
+ 'iwanai' => array(),
1924
+ 'kamifurano' => array(),
1925
+ 'kamikawa' => array(),
1926
+ 'kamishihoro' => array(),
1927
+ 'kamisunagawa' => array(),
1928
+ 'kamoenai' => array(),
1929
+ 'kayabe' => array(),
1930
+ 'kembuchi' => array(),
1931
+ 'kikonai' => array(),
1932
+ 'kimobetsu' => array(),
1933
+ 'kitahiroshima' => array(),
1934
+ 'kitami' => array(),
1935
+ 'kiyosato' => array(),
1936
+ 'koshimizu' => array(),
1937
+ 'kunneppu' => array(),
1938
+ 'kuriyama' => array(),
1939
+ 'kuromatsunai' => array(),
1940
+ 'kushiro' => array(),
1941
+ 'kutchan' => array(),
1942
+ 'kyowa' => array(),
1943
+ 'mashike' => array(),
1944
+ 'matsumae' => array(),
1945
+ 'mikasa' => array(),
1946
+ 'minamifurano' => array(),
1947
+ 'mombetsu' => array(),
1948
+ 'moseushi' => array(),
1949
+ 'mukawa' => array(),
1950
+ 'muroran' => array(),
1951
+ 'naie' => array(),
1952
+ 'nakagawa' => array(),
1953
+ 'nakasatsunai' => array(),
1954
+ 'nakatombetsu' => array(),
1955
+ 'nanae' => array(),
1956
+ 'nanporo' => array(),
1957
+ 'nayoro' => array(),
1958
+ 'nemuro' => array(),
1959
+ 'niikappu' => array(),
1960
+ 'niki' => array(),
1961
+ 'nishiokoppe' => array(),
1962
+ 'noboribetsu' => array(),
1963
+ 'numata' => array(),
1964
+ 'obihiro' => array(),
1965
+ 'obira' => array(),
1966
+ 'oketo' => array(),
1967
+ 'okoppe' => array(),
1968
+ 'otaru' => array(),
1969
+ 'otobe' => array(),
1970
+ 'otofuke' => array(),
1971
+ 'otoineppu' => array(),
1972
+ 'oumu' => array(),
1973
+ 'ozora' => array(),
1974
+ 'pippu' => array(),
1975
+ 'rankoshi' => array(),
1976
+ 'rebun' => array(),
1977
+ 'rikubetsu' => array(),
1978
+ 'rishiri' => array(),
1979
+ 'rishirifuji' => array(),
1980
+ 'saroma' => array(),
1981
+ 'sarufutsu' => array(),
1982
+ 'shakotan' => array(),
1983
+ 'shari' => array(),
1984
+ 'shibecha' => array(),
1985
+ 'shibetsu' => array(),
1986
+ 'shikabe' => array(),
1987
+ 'shikaoi' => array(),
1988
+ 'shimamaki' => array(),
1989
+ 'shimizu' => array(),
1990
+ 'shimokawa' => array(),
1991
+ 'shinshinotsu' => array(),
1992
+ 'shintoku' => array(),
1993
+ 'shiranuka' => array(),
1994
+ 'shiraoi' => array(),
1995
+ 'shiriuchi' => array(),
1996
+ 'sobetsu' => array(),
1997
+ 'sunagawa' => array(),
1998
+ 'taiki' => array(),
1999
+ 'takasu' => array(),
2000
+ 'takikawa' => array(),
2001
+ 'takinoue' => array(),
2002
+ 'teshikaga' => array(),
2003
+ 'tobetsu' => array(),
2004
+ 'tohma' => array(),
2005
+ 'tomakomai' => array(),
2006
+ 'tomari' => array(),
2007
+ 'toya' => array(),
2008
+ 'toyako' => array(),
2009
+ 'toyotomi' => array(),
2010
+ 'toyoura' => array(),
2011
+ 'tsubetsu' => array(),
2012
+ 'tsukigata' => array(),
2013
+ 'urakawa' => array(),
2014
+ 'urausu' => array(),
2015
+ 'uryu' => array(),
2016
+ 'utashinai' => array(),
2017
+ 'wakkanai' => array(),
2018
+ 'wassamu' => array(),
2019
+ 'yakumo' => array(),
2020
+ 'yoichi' => array()),
2021
+ 'hyogo' => array('aioi' => array(),
2022
+ 'akashi' => array(),
2023
+ 'ako' => array(),
2024
+ 'amagasaki' => array(),
2025
+ 'aogaki' => array(),
2026
+ 'asago' => array(),
2027
+ 'ashiya' => array(),
2028
+ 'awaji' => array(),
2029
+ 'fukusaki' => array(),
2030
+ 'goshiki' => array(),
2031
+ 'harima' => array(),
2032
+ 'himeji' => array(),
2033
+ 'ichikawa' => array(),
2034
+ 'inagawa' => array(),
2035
+ 'itami' => array(),
2036
+ 'kakogawa' => array(),
2037
+ 'kamigori' => array(),
2038
+ 'kamikawa' => array(),
2039
+ 'kasai' => array(),
2040
+ 'kasuga' => array(),
2041
+ 'kawanishi' => array(),
2042
+ 'miki' => array(),
2043
+ 'minamiawaji' => array(),
2044
+ 'nishinomiya' => array(),
2045
+ 'nishiwaki' => array(),
2046
+ 'ono' => array(),
2047
+ 'sanda' => array(),
2048
+ 'sannan' => array(),
2049
+ 'sasayama' => array(),
2050
+ 'sayo' => array(),
2051
+ 'shingu' => array(),
2052
+ 'shinonsen' => array(),
2053
+ 'shiso' => array(),
2054
+ 'sumoto' => array(),
2055
+ 'taishi' => array(),
2056
+ 'taka' => array(),
2057
+ 'takarazuka' => array(),
2058
+ 'takasago' => array(),
2059
+ 'takino' => array(),
2060
+ 'tamba' => array(),
2061
+ 'tatsuno' => array(),
2062
+ 'toyooka' => array(),
2063
+ 'yabu' => array(),
2064
+ 'yashiro' => array(),
2065
+ 'yoka' => array(),
2066
+ 'yokawa' => array()),
2067
+ 'ibaraki' => array('ami' => array(),
2068
+ 'asahi' => array(),
2069
+ 'bando' => array(),
2070
+ 'chikusei' => array(),
2071
+ 'daigo' => array(),
2072
+ 'fujishiro' => array(),
2073
+ 'hitachi' => array(),
2074
+ 'hitachinaka' => array(),
2075
+ 'hitachiomiya' => array(),
2076
+ 'hitachiota' => array(),
2077
+ 'ibaraki' => array(),
2078
+ 'ina' => array(),
2079
+ 'inashiki' => array(),
2080
+ 'itako' => array(),
2081
+ 'iwama' => array(),
2082
+ 'joso' => array(),
2083
+ 'kamisu' => array(),
2084
+ 'kasama' => array(),
2085
+ 'kashima' => array(),
2086
+ 'kasumigaura' => array(),
2087
+ 'koga' => array(),
2088
+ 'miho' => array(),
2089
+ 'mito' => array(),
2090
+ 'moriya' => array(),
2091
+ 'naka' => array(),
2092
+ 'namegata' => array(),
2093
+ 'oarai' => array(),
2094
+ 'ogawa' => array(),
2095
+ 'omitama' => array(),
2096
+ 'ryugasaki' => array(),
2097
+ 'sakai' => array(),
2098
+ 'sakuragawa' => array(),
2099
+ 'shimodate' => array(),
2100
+ 'shimotsuma' => array(),
2101
+ 'shirosato' => array(),
2102
+ 'sowa' => array(),
2103
+ 'suifu' => array(),
2104
+ 'takahagi' => array(),
2105
+ 'tamatsukuri' => array(),
2106
+ 'tokai' => array(),
2107
+ 'tomobe' => array(),
2108
+ 'tone' => array(),
2109
+ 'toride' => array(),
2110
+ 'tsuchiura' => array(),
2111
+ 'tsukuba' => array(),
2112
+ 'uchihara' => array(),
2113
+ 'ushiku' => array(),
2114
+ 'yachiyo' => array(),
2115
+ 'yamagata' => array(),
2116
+ 'yawara' => array(),
2117
+ 'yuki' => array()),
2118
+ 'ishikawa' => array('anamizu' => array(),
2119
+ 'hakui' => array(),
2120
+ 'hakusan' => array(),
2121
+ 'kaga' => array(),
2122
+ 'kahoku' => array(),
2123
+ 'kanazawa' => array(),
2124
+ 'kawakita' => array(),
2125
+ 'komatsu' => array(),
2126
+ 'nakanoto' => array(),
2127
+ 'nanao' => array(),
2128
+ 'nomi' => array(),
2129
+ 'nonoichi' => array(),
2130
+ 'noto' => array(),
2131
+ 'shika' => array(),
2132
+ 'suzu' => array(),
2133
+ 'tsubata' => array(),
2134
+ 'tsurugi' => array(),
2135
+ 'uchinada' => array(),
2136
+ 'wajima' => array()),
2137
+ 'iwate' => array('fudai' => array(),
2138
+ 'fujisawa' => array(),
2139
+ 'hanamaki' => array(),
2140
+ 'hiraizumi' => array(),
2141
+ 'hirono' => array(),
2142
+ 'ichinohe' => array(),
2143
+ 'ichinoseki' => array(),
2144
+ 'iwaizumi' => array(),
2145
+ 'iwate' => array(),
2146
+ 'joboji' => array(),
2147
+ 'kamaishi' => array(),
2148
+ 'kanegasaki' => array(),
2149
+ 'karumai' => array(),
2150
+ 'kawai' => array(),
2151
+ 'kitakami' => array(),
2152
+ 'kuji' => array(),
2153
+ 'kunohe' => array(),
2154
+ 'kuzumaki' => array(),
2155
+ 'miyako' => array(),
2156
+ 'mizusawa' => array(),
2157
+ 'morioka' => array(),
2158
+ 'ninohe' => array(),
2159
+ 'noda' => array(),
2160
+ 'ofunato' => array(),
2161
+ 'oshu' => array(),
2162
+ 'otsuchi' => array(),
2163
+ 'rikuzentakata' => array(),
2164
+ 'shiwa' => array(),
2165
+ 'shizukuishi' => array(),
2166
+ 'sumita' => array(),
2167
+ 'tanohata' => array(),
2168
+ 'tono' => array(),
2169
+ 'yahaba' => array(),
2170
+ 'yamada' => array()),
2171
+ 'kagawa' => array('ayagawa' => array(),
2172
+ 'higashikagawa' => array(),
2173
+ 'kanonji' => array(),
2174
+ 'kotohira' => array(),
2175
+ 'manno' => array(),
2176
+ 'marugame' => array(),
2177
+ 'mitoyo' => array(),
2178
+ 'naoshima' => array(),
2179
+ 'sanuki' => array(),
2180
+ 'tadotsu' => array(),
2181
+ 'takamatsu' => array(),
2182
+ 'tonosho' => array(),
2183
+ 'uchinomi' => array(),
2184
+ 'utazu' => array(),
2185
+ 'zentsuji' => array()),
2186
+ 'kagoshima' => array('akune' => array(),
2187
+ 'amami' => array(),
2188
+ 'hioki' => array(),
2189
+ 'isa' => array(),
2190
+ 'isen' => array(),
2191
+ 'izumi' => array(),
2192
+ 'kagoshima' => array(),
2193
+ 'kanoya' => array(),
2194
+ 'kawanabe' => array(),
2195
+ 'kinko' => array(),
2196
+ 'kouyama' => array(),
2197
+ 'makurazaki' => array(),
2198
+ 'matsumoto' => array(),
2199
+ 'minamitane' => array(),
2200
+ 'nakatane' => array(),
2201
+ 'nishinoomote' => array(),
2202
+ 'satsumasendai' => array(),
2203
+ 'soo' => array(),
2204
+ 'tarumizu' => array(),
2205
+ 'yusui' => array()),
2206
+ 'kanagawa' => array('aikawa' => array(),
2207
+ 'atsugi' => array(),
2208
+ 'ayase' => array(),
2209
+ 'chigasaki' => array(),
2210
+ 'ebina' => array(),
2211
+ 'fujisawa' => array(),
2212
+ 'hadano' => array(),
2213
+ 'hakone' => array(),
2214
+ 'hiratsuka' => array(),
2215
+ 'isehara' => array(),
2216
+ 'kaisei' => array(),
2217
+ 'kamakura' => array(),
2218
+ 'kiyokawa' => array(),
2219
+ 'matsuda' => array(),
2220
+ 'minamiashigara' => array(),
2221
+ 'miura' => array(),
2222
+ 'nakai' => array(),
2223
+ 'ninomiya' => array(),
2224
+ 'odawara' => array(),
2225
+ 'oi' => array(),
2226
+ 'oiso' => array(),
2227
+ 'sagamihara' => array(),
2228
+ 'samukawa' => array(),
2229
+ 'tsukui' => array(),
2230
+ 'yamakita' => array(),
2231
+ 'yamato' => array(),
2232
+ 'yokosuka' => array(),
2233
+ 'yugawara' => array(),
2234
+ 'zama' => array(),
2235
+ 'zushi' => array()),
2236
+ 'kochi' => array('aki' => array(),
2237
+ 'geisei' => array(),
2238
+ 'hidaka' => array(),
2239
+ 'higashitsuno' => array(),
2240
+ 'ino' => array(),
2241
+ 'kagami' => array(),
2242
+ 'kami' => array(),
2243
+ 'kitagawa' => array(),
2244
+ 'kochi' => array(),
2245
+ 'mihara' => array(),
2246
+ 'motoyama' => array(),
2247
+ 'muroto' => array(),
2248
+ 'nahari' => array(),
2249
+ 'nakamura' => array(),
2250
+ 'nankoku' => array(),
2251
+ 'nishitosa' => array(),
2252
+ 'niyodogawa' => array(),
2253
+ 'ochi' => array(),
2254
+ 'okawa' => array(),
2255
+ 'otoyo' => array(),
2256
+ 'otsuki' => array(),
2257
+ 'sakawa' => array(),
2258
+ 'sukumo' => array(),
2259
+ 'susaki' => array(),
2260
+ 'tosa' => array(),
2261
+ 'tosashimizu' => array(),
2262
+ 'toyo' => array(),
2263
+ 'tsuno' => array(),
2264
+ 'umaji' => array(),
2265
+ 'yasuda' => array(),
2266
+ 'yusuhara' => array()),
2267
+ 'kumamoto' => array('amakusa' => array(),
2268
+ 'arao' => array(),
2269
+ 'aso' => array(),
2270
+ 'choyo' => array(),
2271
+ 'gyokuto' => array(),
2272
+ 'hitoyoshi' => array(),
2273
+ 'kamiamakusa' => array(),
2274
+ 'kashima' => array(),
2275
+ 'kikuchi' => array(),
2276
+ 'kosa' => array(),
2277
+ 'kumamoto' => array(),
2278
+ 'mashiki' => array(),
2279
+ 'mifune' => array(),
2280
+ 'minamata' => array(),
2281
+ 'minamioguni' => array(),
2282
+ 'nagasu' => array(),
2283
+ 'nishihara' => array(),
2284
+ 'oguni' => array(),
2285
+ 'ozu' => array(),
2286
+ 'sumoto' => array(),
2287
+ 'takamori' => array(),
2288
+ 'uki' => array(),
2289
+ 'uto' => array(),
2290
+ 'yamaga' => array(),
2291
+ 'yamato' => array(),
2292
+ 'yatsushiro' => array()),
2293
+ 'kyoto' => array('ayabe' => array(),
2294
+ 'fukuchiyama' => array(),
2295
+ 'higashiyama' => array(),
2296
+ 'ide' => array(),
2297
+ 'ine' => array(),
2298
+ 'joyo' => array(),
2299
+ 'kameoka' => array(),
2300
+ 'kamo' => array(),
2301
+ 'kita' => array(),
2302
+ 'kizu' => array(),
2303
+ 'kumiyama' => array(),
2304
+ 'kyotamba' => array(),
2305
+ 'kyotanabe' => array(),
2306
+ 'kyotango' => array(),
2307
+ 'maizuru' => array(),
2308
+ 'minami' => array(),
2309
+ 'minamiyamashiro' => array(),
2310
+ 'miyazu' => array(),
2311
+ 'muko' => array(),
2312
+ 'nagaokakyo' => array(),
2313
+ 'nakagyo' => array(),
2314
+ 'nantan' => array(),
2315
+ 'oyamazaki' => array(),
2316
+ 'sakyo' => array(),
2317
+ 'seika' => array(),
2318
+ 'tanabe' => array(),
2319
+ 'uji' => array(),
2320
+ 'ujitawara' => array(),
2321
+ 'wazuka' => array(),
2322
+ 'yamashina' => array(),
2323
+ 'yawata' => array()),
2324
+ 'mie' => array('asahi' => array(),
2325
+ 'inabe' => array(),
2326
+ 'ise' => array(),
2327
+ 'kameyama' => array(),
2328
+ 'kawagoe' => array(),
2329
+ 'kiho' => array(),
2330
+ 'kisosaki' => array(),
2331
+ 'kiwa' => array(),
2332
+ 'komono' => array(),
2333
+ 'kumano' => array(),
2334
+ 'kuwana' => array(),
2335
+ 'matsusaka' => array(),
2336
+ 'meiwa' => array(),
2337
+ 'mihama' => array(),
2338
+ 'minamiise' => array(),
2339
+ 'misugi' => array(),
2340
+ 'miyama' => array(),
2341
+ 'nabari' => array(),
2342
+ 'shima' => array(),
2343
+ 'suzuka' => array(),
2344
+ 'tado' => array(),
2345
+ 'taiki' => array(),
2346
+ 'taki' => array(),
2347
+ 'tamaki' => array(),
2348
+ 'toba' => array(),
2349
+ 'tsu' => array(),
2350
+ 'udono' => array(),
2351
+ 'ureshino' => array(),
2352
+ 'watarai' => array(),
2353
+ 'yokkaichi' => array()),
2354
+ 'miyagi' => array('furukawa' => array(),
2355
+ 'higashimatsushima' => array(),
2356
+ 'ishinomaki' => array(),
2357
+ 'iwanuma' => array(),
2358
+ 'kakuda' => array(),
2359
+ 'kami' => array(),
2360
+ 'kawasaki' => array(),
2361
+ 'kesennuma' => array(),
2362
+ 'marumori' => array(),
2363
+ 'matsushima' => array(),
2364
+ 'minamisanriku' => array(),
2365
+ 'misato' => array(),
2366
+ 'murata' => array(),
2367
+ 'natori' => array(),
2368
+ 'ogawara' => array(),
2369
+ 'ohira' => array(),
2370
+ 'onagawa' => array(),
2371
+ 'osaki' => array(),
2372
+ 'rifu' => array(),
2373
+ 'semine' => array(),
2374
+ 'shibata' => array(),
2375
+ 'shichikashuku' => array(),
2376
+ 'shikama' => array(),
2377
+ 'shiogama' => array(),
2378
+ 'shiroishi' => array(),
2379
+ 'tagajo' => array(),
2380
+ 'taiwa' => array(),
2381
+ 'tome' => array(),
2382
+ 'tomiya' => array(),
2383
+ 'wakuya' => array(),
2384
+ 'watari' => array(),
2385
+ 'yamamoto' => array(),
2386
+ 'zao' => array()),
2387
+ 'miyazaki' => array('aya' => array(),
2388
+ 'ebino' => array(),
2389
+ 'gokase' => array(),
2390
+ 'hyuga' => array(),
2391
+ 'kadogawa' => array(),
2392
+ 'kawaminami' => array(),
2393
+ 'kijo' => array(),
2394
+ 'kitagawa' => array(),
2395
+ 'kitakata' => array(),
2396
+ 'kitaura' => array(),
2397
+ 'kobayashi' => array(),
2398
+ 'kunitomi' => array(),
2399
+ 'kushima' => array(),
2400
+ 'mimata' => array(),
2401
+ 'miyakonojo' => array(),
2402
+ 'miyazaki' => array(),
2403
+ 'morotsuka' => array(),
2404
+ 'nichinan' => array(),
2405
+ 'nishimera' => array(),
2406
+ 'nobeoka' => array(),
2407
+ 'saito' => array(),
2408
+ 'shiiba' => array(),
2409
+ 'shintomi' => array(),
2410
+ 'takaharu' => array(),
2411
+ 'takanabe' => array(),
2412
+ 'takazaki' => array(),
2413
+ 'tsuno' => array()),
2414
+ 'nagano' => array('achi' => array(),
2415
+ 'agematsu' => array(),
2416
+ 'anan' => array(),
2417
+ 'aoki' => array(),
2418
+ 'asahi' => array(),
2419
+ 'azumino' => array(),
2420
+ 'chikuhoku' => array(),
2421
+ 'chikuma' => array(),
2422
+ 'chino' => array(),
2423
+ 'fujimi' => array(),
2424
+ 'hakuba' => array(),
2425
+ 'hara' => array(),
2426
+ 'hiraya' => array(),
2427
+ 'iida' => array(),
2428
+ 'iijima' => array(),
2429
+ 'iiyama' => array(),
2430
+ 'iizuna' => array(),
2431
+ 'ikeda' => array(),
2432
+ 'ikusaka' => array(),
2433
+ 'ina' => array(),
2434
+ 'karuizawa' => array(),
2435
+ 'kawakami' => array(),
2436
+ 'kiso' => array(),
2437
+ 'kisofukushima' => array(),
2438
+ 'kitaaiki' => array(),
2439
+ 'komagane' => array(),
2440
+ 'komoro' => array(),
2441
+ 'matsukawa' => array(),
2442
+ 'matsumoto' => array(),
2443
+ 'miasa' => array(),
2444
+ 'minamiaiki' => array(),
2445
+ 'minamimaki' => array(),
2446
+ 'minamiminowa' => array(),
2447
+ 'minowa' => array(),
2448
+ 'miyada' => array(),
2449
+ 'miyota' => array(),
2450
+ 'mochizuki' => array(),
2451
+ 'nagano' => array(),
2452
+ 'nagawa' => array(),
2453
+ 'nagiso' => array(),
2454
+ 'nakagawa' => array(),
2455
+ 'nakano' => array(),
2456
+ 'nozawaonsen' => array(),
2457
+ 'obuse' => array(),
2458
+ 'ogawa' => array(),
2459
+ 'okaya' => array(),
2460
+ 'omachi' => array(),
2461
+ 'omi' => array(),
2462
+ 'ookuwa' => array(),
2463
+ 'ooshika' => array(),
2464
+ 'otaki' => array(),
2465
+ 'otari' => array(),
2466
+ 'sakae' => array(),
2467
+ 'sakaki' => array(),
2468
+ 'saku' => array(),
2469
+ 'sakuho' => array(),
2470
+ 'shimosuwa' => array(),
2471
+ 'shinanomachi' => array(),
2472
+ 'shiojiri' => array(),
2473
+ 'suwa' => array(),
2474
+ 'suzaka' => array(),
2475
+ 'takagi' => array(),
2476
+ 'takamori' => array(),
2477
+ 'takayama' => array(),
2478
+ 'tateshina' => array(),
2479
+ 'tatsuno' => array(),
2480
+ 'togakushi' => array(),
2481
+ 'togura' => array(),
2482
+ 'tomi' => array(),
2483
+ 'ueda' => array(),
2484
+ 'wada' => array(),
2485
+ 'yamagata' => array(),
2486
+ 'yamanouchi' => array(),
2487
+ 'yasaka' => array(),
2488
+ 'yasuoka' => array()),
2489
+ 'nagasaki' => array('chijiwa' => array(),
2490
+ 'futsu' => array(),
2491
+ 'goto' => array(),
2492
+ 'hasami' => array(),
2493
+ 'hirado' => array(),
2494
+ 'iki' => array(),
2495
+ 'isahaya' => array(),
2496
+ 'kawatana' => array(),
2497
+ 'kuchinotsu' => array(),
2498
+ 'matsuura' => array(),
2499
+ 'nagasaki' => array(),
2500
+ 'obama' => array(),
2501
+ 'omura' => array(),
2502
+ 'oseto' => array(),
2503
+ 'saikai' => array(),
2504
+ 'sasebo' => array(),
2505
+ 'seihi' => array(),
2506
+ 'shimabara' => array(),
2507
+ 'shinkamigoto' => array(),
2508
+ 'togitsu' => array(),
2509
+ 'tsushima' => array(),
2510
+ 'unzen' => array()),
2511
+ 'nara' => array('ando' => array(),
2512
+ 'gose' => array(),
2513
+ 'heguri' => array(),
2514
+ 'higashiyoshino' => array(),
2515
+ 'ikaruga' => array(),
2516
+ 'ikoma' => array(),
2517
+ 'kamikitayama' => array(),
2518
+ 'kanmaki' => array(),
2519
+ 'kashiba' => array(),
2520
+ 'kashihara' => array(),
2521
+ 'katsuragi' => array(),
2522
+ 'kawai' => array(),
2523
+ 'kawakami' => array(),
2524
+ 'kawanishi' => array(),
2525
+ 'koryo' => array(),
2526
+ 'kurotaki' => array(),
2527
+ 'mitsue' => array(),
2528
+ 'miyake' => array(),
2529
+ 'nara' => array(),
2530
+ 'nosegawa' => array(),
2531
+ 'oji' => array(),
2532
+ 'ouda' => array(),
2533
+ 'oyodo' => array(),
2534
+ 'sakurai' => array(),
2535
+ 'sango' => array(),
2536
+ 'shimoichi' => array(),
2537
+ 'shimokitayama' => array(),
2538
+ 'shinjo' => array(),
2539
+ 'soni' => array(),
2540
+ 'takatori' => array(),
2541
+ 'tawaramoto' => array(),
2542
+ 'tenkawa' => array(),
2543
+ 'tenri' => array(),
2544
+ 'uda' => array(),
2545
+ 'yamatokoriyama' => array(),
2546
+ 'yamatotakada' => array(),
2547
+ 'yamazoe' => array(),
2548
+ 'yoshino' => array()),
2549
+ 'niigata' => array('aga' => array(),
2550
+ 'agano' => array(),
2551
+ 'gosen' => array(),
2552
+ 'itoigawa' => array(),
2553
+ 'izumozaki' => array(),
2554
+ 'joetsu' => array(),
2555
+ 'kamo' => array(),
2556
+ 'kariwa' => array(),
2557
+ 'kashiwazaki' => array(),
2558
+ 'minamiuonuma' => array(),
2559
+ 'mitsuke' => array(),
2560
+ 'muika' => array(),
2561
+ 'murakami' => array(),
2562
+ 'myoko' => array(),
2563
+ 'nagaoka' => array(),
2564
+ 'niigata' => array(),
2565
+ 'ojiya' => array(),
2566
+ 'omi' => array(),
2567
+ 'sado' => array(),
2568
+ 'sanjo' => array(),
2569
+ 'seiro' => array(),
2570
+ 'seirou' => array(),
2571
+ 'sekikawa' => array(),
2572
+ 'shibata' => array(),
2573
+ 'tagami' => array(),
2574
+ 'tainai' => array(),
2575
+ 'tochio' => array(),
2576
+ 'tokamachi' => array(),
2577
+ 'tsubame' => array(),
2578
+ 'tsunan' => array(),
2579
+ 'uonuma' => array(),
2580
+ 'yahiko' => array(),
2581
+ 'yoita' => array(),
2582
+ 'yuzawa' => array()),
2583
+ 'oita' => array('beppu' => array(),
2584
+ 'bungoono' => array(),
2585
+ 'bungotakada' => array(),
2586
+ 'hasama' => array(),
2587
+ 'hiji' => array(),
2588
+ 'himeshima' => array(),
2589
+ 'hita' => array(),
2590
+ 'kamitsue' => array(),
2591
+ 'kokonoe' => array(),
2592
+ 'kuju' => array(),
2593
+ 'kunisaki' => array(),
2594
+ 'kusu' => array(),
2595
+ 'oita' => array(),
2596
+ 'saiki' => array(),
2597
+ 'taketa' => array(),
2598
+ 'tsukumi' => array(),
2599
+ 'usa' => array(),
2600
+ 'usuki' => array(),
2601
+ 'yufu' => array()),
2602
+ 'okayama' => array('akaiwa' => array(),
2603
+ 'asakuchi' => array(),
2604
+ 'bizen' => array(),
2605
+ 'hayashima' => array(),
2606
+ 'ibara' => array(),
2607
+ 'kagamino' => array(),
2608
+ 'kasaoka' => array(),
2609
+ 'kibichuo' => array(),
2610
+ 'kumenan' => array(),
2611
+ 'kurashiki' => array(),
2612
+ 'maniwa' => array(),
2613
+ 'misaki' => array(),
2614
+ 'nagi' => array(),
2615
+ 'niimi' => array(),
2616
+ 'nishiawakura' => array(),
2617
+ 'okayama' => array(),
2618
+ 'satosho' => array(),
2619
+ 'setouchi' => array(),
2620
+ 'shinjo' => array(),
2621
+ 'shoo' => array(),
2622
+ 'soja' => array(),
2623
+ 'takahashi' => array(),
2624
+ 'tamano' => array(),
2625
+ 'tsuyama' => array(),
2626
+ 'wake' => array(),
2627
+ 'yakage' => array()),
2628
+ 'okinawa' => array('aguni' => array(),
2629
+ 'ginowan' => array(),
2630
+ 'ginoza' => array(),
2631
+ 'gushikami' => array(),
2632
+ 'haebaru' => array(),
2633
+ 'higashi' => array(),
2634
+ 'hirara' => array(),
2635
+ 'iheya' => array(),
2636
+ 'ishigaki' => array(),
2637
+ 'ishikawa' => array(),
2638
+ 'itoman' => array(),
2639
+ 'izena' => array(),
2640
+ 'kadena' => array(),
2641
+ 'kin' => array(),
2642
+ 'kitadaito' => array(),
2643
+ 'kitanakagusuku' => array(),
2644
+ 'kumejima' => array(),
2645
+ 'kunigami' => array(),
2646
+ 'minamidaito' => array(),
2647
+ 'motobu' => array(),
2648
+ 'nago' => array(),
2649
+ 'naha' => array(),
2650
+ 'nakagusuku' => array(),
2651
+ 'nakijin' => array(),
2652
+ 'nanjo' => array(),
2653
+ 'nishihara' => array(),
2654
+ 'ogimi' => array(),
2655
+ 'okinawa' => array(),
2656
+ 'onna' => array(),
2657
+ 'shimoji' => array(),
2658
+ 'taketomi' => array(),
2659
+ 'tarama' => array(),
2660
+ 'tokashiki' => array(),
2661
+ 'tomigusuku' => array(),
2662
+ 'tonaki' => array(),
2663
+ 'urasoe' => array(),
2664
+ 'uruma' => array(),
2665
+ 'yaese' => array(),
2666
+ 'yomitan' => array(),
2667
+ 'yonabaru' => array(),
2668
+ 'yonaguni' => array(),
2669
+ 'zamami' => array()),
2670
+ 'osaka' => array('abeno' => array(),
2671
+ 'chihayaakasaka' => array(),
2672
+ 'chuo' => array(),
2673
+ 'daito' => array(),
2674
+ 'fujiidera' => array(),
2675
+ 'habikino' => array(),
2676
+ 'hannan' => array(),
2677
+ 'higashiosaka' => array(),
2678
+ 'higashisumiyoshi' => array(),
2679
+ 'higashiyodogawa' => array(),
2680
+ 'hirakata' => array(),
2681
+ 'ibaraki' => array(),
2682
+ 'ikeda' => array(),
2683
+ 'izumi' => array(),
2684
+ 'izumiotsu' => array(),
2685
+ 'izumisano' => array(),
2686
+ 'kadoma' => array(),
2687
+ 'kaizuka' => array(),
2688
+ 'kanan' => array(),
2689
+ 'kashiwara' => array(),
2690
+ 'katano' => array(),
2691
+ 'kawachinagano' => array(),
2692
+ 'kishiwada' => array(),
2693
+ 'kita' => array(),
2694
+ 'kumatori' => array(),
2695
+ 'matsubara' => array(),
2696
+ 'minato' => array(),
2697
+ 'minoh' => array(),
2698
+ 'misaki' => array(),
2699
+ 'moriguchi' => array(),
2700
+ 'neyagawa' => array(),
2701
+ 'nishi' => array(),
2702
+ 'nose' => array(),
2703
+ 'osakasayama' => array(),
2704
+ 'sakai' => array(),
2705
+ 'sayama' => array(),
2706
+ 'sennan' => array(),
2707
+ 'settsu' => array(),
2708
+ 'shijonawate' => array(),
2709
+ 'shimamoto' => array(),
2710
+ 'suita' => array(),
2711
+ 'tadaoka' => array(),
2712
+ 'taishi' => array(),
2713
+ 'tajiri' => array(),
2714
+ 'takaishi' => array(),
2715
+ 'takatsuki' => array(),
2716
+ 'tondabayashi' => array(),
2717
+ 'toyonaka' => array(),
2718
+ 'toyono' => array(),
2719
+ 'yao' => array()),
2720
+ 'saga' => array('ariake' => array(),
2721
+ 'arita' => array(),
2722
+ 'fukudomi' => array(),
2723
+ 'genkai' => array(),
2724
+ 'hamatama' => array(),
2725
+ 'hizen' => array(),
2726
+ 'imari' => array(),
2727
+ 'kamimine' => array(),
2728
+ 'kanzaki' => array(),
2729
+ 'karatsu' => array(),
2730
+ 'kashima' => array(),
2731
+ 'kitagata' => array(),
2732
+ 'kitahata' => array(),
2733
+ 'kiyama' => array(),
2734
+ 'kouhoku' => array(),
2735
+ 'kyuragi' => array(),
2736
+ 'nishiarita' => array(),
2737
+ 'ogi' => array(),
2738
+ 'omachi' => array(),
2739
+ 'ouchi' => array(),
2740
+ 'saga' => array(),
2741
+ 'shiroishi' => array(),
2742
+ 'taku' => array(),
2743
+ 'tara' => array(),
2744
+ 'tosu' => array(),
2745
+ 'yoshinogari' => array()),
2746
+ 'saitama' => array('arakawa' => array(),
2747
+ 'asaka' => array(),
2748
+ 'chichibu' => array(),
2749
+ 'fujimi' => array(),
2750
+ 'fujimino' => array(),
2751
+ 'fukaya' => array(),
2752
+ 'hanno' => array(),
2753
+ 'hanyu' => array(),
2754
+ 'hasuda' => array(),
2755
+ 'hatogaya' => array(),
2756
+ 'hatoyama' => array(),
2757
+ 'hidaka' => array(),
2758
+ 'higashichichibu' => array(),
2759
+ 'higashimatsuyama' => array(),
2760
+ 'honjo' => array(),
2761
+ 'ina' => array(),
2762
+ 'iruma' => array(),
2763
+ 'iwatsuki' => array(),
2764
+ 'kamiizumi' => array(),
2765
+ 'kamikawa' => array(),
2766
+ 'kamisato' => array(),
2767
+ 'kasukabe' => array(),
2768
+ 'kawagoe' => array(),
2769
+ 'kawaguchi' => array(),
2770
+ 'kawajima' => array(),
2771
+ 'kazo' => array(),
2772
+ 'kitamoto' => array(),
2773
+ 'koshigaya' => array(),
2774
+ 'kounosu' => array(),
2775
+ 'kuki' => array(),
2776
+ 'kumagaya' => array(),
2777
+ 'matsubushi' => array(),
2778
+ 'minano' => array(),
2779
+ 'misato' => array(),
2780
+ 'miyashiro' => array(),
2781
+ 'miyoshi' => array(),
2782
+ 'moroyama' => array(),
2783
+ 'nagatoro' => array(),
2784
+ 'namegawa' => array(),
2785
+ 'niiza' => array(),
2786
+ 'ogano' => array(),
2787
+ 'ogawa' => array(),
2788
+ 'ogose' => array(),
2789
+ 'okegawa' => array(),
2790
+ 'omiya' => array(),
2791
+ 'otaki' => array(),
2792
+ 'ranzan' => array(),
2793
+ 'ryokami' => array(),
2794
+ 'saitama' => array(),
2795
+ 'sakado' => array(),
2796
+ 'satte' => array(),
2797
+ 'sayama' => array(),
2798
+ 'shiki' => array(),
2799
+ 'shiraoka' => array(),
2800
+ 'soka' => array(),
2801
+ 'sugito' => array(),
2802
+ 'toda' => array(),
2803
+ 'tokigawa' => array(),
2804
+ 'tokorozawa' => array(),
2805
+ 'tsurugashima' => array(),
2806
+ 'urawa' => array(),
2807
+ 'warabi' => array(),
2808
+ 'yashio' => array(),
2809
+ 'yokoze' => array(),
2810
+ 'yono' => array(),
2811
+ 'yorii' => array(),
2812
+ 'yoshida' => array(),
2813
+ 'yoshikawa' => array(),
2814
+ 'yoshimi' => array()),
2815
+ 'shiga' => array('aisho' => array(),
2816
+ 'gamo' => array(),
2817
+ 'higashiomi' => array(),
2818
+ 'hikone' => array(),
2819
+ 'koka' => array(),
2820
+ 'konan' => array(),
2821
+ 'kosei' => array(),
2822
+ 'koto' => array(),
2823
+ 'kusatsu' => array(),
2824
+ 'maibara' => array(),
2825
+ 'moriyama' => array(),
2826
+ 'nagahama' => array(),
2827
+ 'nishiazai' => array(),
2828
+ 'notogawa' => array(),
2829
+ 'omihachiman' => array(),
2830
+ 'otsu' => array(),
2831
+ 'ritto' => array(),
2832
+ 'ryuoh' => array(),
2833
+ 'takashima' => array(),
2834
+ 'takatsuki' => array(),
2835
+ 'torahime' => array(),
2836
+ 'toyosato' => array(),
2837
+ 'yasu' => array()),
2838
+ 'shimane' => array('akagi' => array(),
2839
+ 'ama' => array(),
2840
+ 'gotsu' => array(),
2841
+ 'hamada' => array(),
2842
+ 'higashiizumo' => array(),
2843
+ 'hikawa' => array(),
2844
+ 'hikimi' => array(),
2845
+ 'izumo' => array(),
2846
+ 'kakinoki' => array(),
2847
+ 'masuda' => array(),
2848
+ 'matsue' => array(),
2849
+ 'misato' => array(),
2850
+ 'nishinoshima' => array(),
2851
+ 'ohda' => array(),
2852
+ 'okinoshima' => array(),
2853
+ 'okuizumo' => array(),
2854
+ 'shimane' => array(),
2855
+ 'tamayu' => array(),
2856
+ 'tsuwano' => array(),
2857
+ 'unnan' => array(),
2858
+ 'yakumo' => array(),
2859
+ 'yasugi' => array(),
2860
+ 'yatsuka' => array()),
2861
+ 'shizuoka' => array('arai' => array(),
2862
+ 'atami' => array(),
2863
+ 'fuji' => array(),
2864
+ 'fujieda' => array(),
2865
+ 'fujikawa' => array(),
2866
+ 'fujinomiya' => array(),
2867
+ 'fukuroi' => array(),
2868
+ 'gotemba' => array(),
2869
+ 'haibara' => array(),
2870
+ 'hamamatsu' => array(),
2871
+ 'higashiizu' => array(),
2872
+ 'ito' => array(),
2873
+ 'iwata' => array(),
2874
+ 'izu' => array(),
2875
+ 'izunokuni' => array(),
2876
+ 'kakegawa' => array(),
2877
+ 'kannami' => array(),
2878
+ 'kawanehon' => array(),
2879
+ 'kawazu' => array(),
2880
+ 'kikugawa' => array(),
2881
+ 'kosai' => array(),
2882
+ 'makinohara' => array(),
2883
+ 'matsuzaki' => array(),
2884
+ 'minamiizu' => array(),
2885
+ 'mishima' => array(),
2886
+ 'morimachi' => array(),
2887
+ 'nishiizu' => array(),
2888
+ 'numazu' => array(),
2889
+ 'omaezaki' => array(),
2890
+ 'shimada' => array(),
2891
+ 'shimizu' => array(),
2892
+ 'shimoda' => array(),
2893
+ 'shizuoka' => array(),
2894
+ 'susono' => array(),
2895
+ 'yaizu' => array(),
2896
+ 'yoshida' => array()),
2897
+ 'tochigi' => array('ashikaga' => array(),
2898
+ 'bato' => array(),
2899
+ 'haga' => array(),
2900
+ 'ichikai' => array(),
2901
+ 'iwafune' => array(),
2902
+ 'kaminokawa' => array(),
2903
+ 'kanuma' => array(),
2904
+ 'karasuyama' => array(),
2905
+ 'kuroiso' => array(),
2906
+ 'mashiko' => array(),
2907
+ 'mibu' => array(),
2908
+ 'moka' => array(),
2909
+ 'motegi' => array(),
2910
+ 'nasu' => array(),
2911
+ 'nasushiobara' => array(),
2912
+ 'nikko' => array(),
2913
+ 'nishikata' => array(),
2914
+ 'nogi' => array(),
2915
+ 'ohira' => array(),
2916
+ 'ohtawara' => array(),
2917
+ 'oyama' => array(),
2918
+ 'sakura' => array(),
2919
+ 'sano' => array(),
2920
+ 'shimotsuke' => array(),
2921
+ 'shioya' => array(),
2922
+ 'takanezawa' => array(),
2923
+ 'tochigi' => array(),
2924
+ 'tsuga' => array(),
2925
+ 'ujiie' => array(),
2926
+ 'utsunomiya' => array(),
2927
+ 'yaita' => array()),
2928
+ 'tokushima' => array('aizumi' => array(),
2929
+ 'anan' => array(),
2930
+ 'ichiba' => array(),
2931
+ 'itano' => array(),
2932
+ 'kainan' => array(),
2933
+ 'komatsushima' => array(),
2934
+ 'matsushige' => array(),
2935
+ 'mima' => array(),
2936
+ 'minami' => array(),
2937
+ 'miyoshi' => array(),
2938
+ 'mugi' => array(),
2939
+ 'nakagawa' => array(),
2940
+ 'naruto' => array(),
2941
+ 'sanagochi' => array(),
2942
+ 'shishikui' => array(),
2943
+ 'tokushima' => array(),
2944
+ 'wajiki' => array()),
2945
+ 'tokyo' => array('adachi' => array(),
2946
+ 'akiruno' => array(),
2947
+ 'akishima' => array(),
2948
+ 'aogashima' => array(),
2949
+ 'arakawa' => array(),
2950
+ 'bunkyo' => array(),
2951
+ 'chiyoda' => array(),
2952
+ 'chofu' => array(),
2953
+ 'chuo' => array(),
2954
+ 'edogawa' => array(),
2955
+ 'fuchu' => array(),
2956
+ 'fussa' => array(),
2957
+ 'hachijo' => array(),
2958
+ 'hachioji' => array(),
2959
+ 'hamura' => array(),
2960
+ 'higashikurume' => array(),
2961
+ 'higashimurayama' => array(),
2962
+ 'higashiyamato' => array(),
2963
+ 'hino' => array(),
2964
+ 'hinode' => array(),
2965
+ 'hinohara' => array(),
2966
+ 'inagi' => array(),
2967
+ 'itabashi' => array(),
2968
+ 'katsushika' => array(),
2969
+ 'kita' => array(),
2970
+ 'kiyose' => array(),
2971
+ 'kodaira' => array(),
2972
+ 'koganei' => array(),
2973
+ 'kokubunji' => array(),
2974
+ 'komae' => array(),
2975
+ 'koto' => array(),
2976
+ 'kouzushima' => array(),
2977
+ 'kunitachi' => array(),
2978
+ 'machida' => array(),
2979
+ 'meguro' => array(),
2980
+ 'minato' => array(),
2981
+ 'mitaka' => array(),
2982
+ 'mizuho' => array(),
2983
+ 'musashimurayama' => array(),
2984
+ 'musashino' => array(),
2985
+ 'nakano' => array(),
2986
+ 'nerima' => array(),
2987
+ 'ogasawara' => array(),
2988
+ 'okutama' => array(),
2989
+ 'ome' => array(),
2990
+ 'oshima' => array(),
2991
+ 'ota' => array(),
2992
+ 'setagaya' => array(),
2993
+ 'shibuya' => array(),
2994
+ 'shinagawa' => array(),
2995
+ 'shinjuku' => array(),
2996
+ 'suginami' => array(),
2997
+ 'sumida' => array(),
2998
+ 'tachikawa' => array(),
2999
+ 'taito' => array(),
3000
+ 'tama' => array(),
3001
+ 'toshima' => array()),
3002
+ 'tottori' => array('chizu' => array(),
3003
+ 'hino' => array(),
3004
+ 'kawahara' => array(),
3005
+ 'koge' => array(),
3006
+ 'kotoura' => array(),
3007
+ 'misasa' => array(),
3008
+ 'nanbu' => array(),
3009
+ 'nichinan' => array(),
3010
+ 'sakaiminato' => array(),
3011
+ 'tottori' => array(),
3012
+ 'wakasa' => array(),
3013
+ 'yazu' => array(),
3014
+ 'yonago' => array()),
3015
+ 'toyama' => array('asahi' => array(),
3016
+ 'fuchu' => array(),
3017
+ 'fukumitsu' => array(),
3018
+ 'funahashi' => array(),
3019
+ 'himi' => array(),
3020
+ 'imizu' => array(),
3021
+ 'inami' => array(),
3022
+ 'johana' => array(),
3023
+ 'kamiichi' => array(),
3024
+ 'kurobe' => array(),
3025
+ 'nakaniikawa' => array(),
3026
+ 'namerikawa' => array(),
3027
+ 'nanto' => array(),
3028
+ 'nyuzen' => array(),
3029
+ 'oyabe' => array(),
3030
+ 'taira' => array(),
3031
+ 'takaoka' => array(),
3032
+ 'tateyama' => array(),
3033
+ 'toga' => array(),
3034
+ 'tonami' => array(),
3035
+ 'toyama' => array(),
3036
+ 'unazuki' => array(),
3037
+ 'uozu' => array(),
3038
+ 'yamada' => array()),
3039
+ 'wakayama' => array('arida' => array(),
3040
+ 'aridagawa' => array(),
3041
+ 'gobo' => array(),
3042
+ 'hashimoto' => array(),
3043
+ 'hidaka' => array(),
3044
+ 'hirogawa' => array(),
3045
+ 'inami' => array(),
3046
+ 'iwade' => array(),
3047
+ 'kainan' => array(),
3048
+ 'kamitonda' => array(),
3049
+ 'katsuragi' => array(),
3050
+ 'kimino' => array(),
3051
+ 'kinokawa' => array(),
3052
+ 'kitayama' => array(),
3053
+ 'koya' => array(),
3054
+ 'koza' => array(),
3055
+ 'kozagawa' => array(),
3056
+ 'kudoyama' => array(),
3057
+ 'kushimoto' => array(),
3058
+ 'mihama' => array(),
3059
+ 'misato' => array(),
3060
+ 'nachikatsuura' => array(),
3061
+ 'shingu' => array(),
3062
+ 'shirahama' => array(),
3063
+ 'taiji' => array(),
3064
+ 'tanabe' => array(),
3065
+ 'wakayama' => array(),
3066
+ 'yuasa' => array(),
3067
+ 'yura' => array()),
3068
+ 'yamagata' => array('asahi' => array(),
3069
+ 'funagata' => array(),
3070
+ 'higashine' => array(),
3071
+ 'iide' => array(),
3072
+ 'kahoku' => array(),
3073
+ 'kaminoyama' => array(),
3074
+ 'kaneyama' => array(),
3075
+ 'kawanishi' => array(),
3076
+ 'mamurogawa' => array(),
3077
+ 'mikawa' => array(),
3078
+ 'murayama' => array(),
3079
+ 'nagai' => array(),
3080
+ 'nakayama' => array(),
3081
+ 'nanyo' => array(),
3082
+ 'nishikawa' => array(),
3083
+ 'obanazawa' => array(),
3084
+ 'oe' => array(),
3085
+ 'oguni' => array(),
3086
+ 'ohkura' => array(),
3087
+ 'oishida' => array(),
3088
+ 'sagae' => array(),
3089
+ 'sakata' => array(),
3090
+ 'sakegawa' => array(),
3091
+ 'shinjo' => array(),
3092
+ 'shirataka' => array(),
3093
+ 'shonai' => array(),
3094
+ 'takahata' => array(),
3095
+ 'tendo' => array(),
3096
+ 'tozawa' => array(),
3097
+ 'tsuruoka' => array(),
3098
+ 'yamagata' => array(),
3099
+ 'yamanobe' => array(),
3100
+ 'yonezawa' => array(),
3101
+ 'yuza' => array()),
3102
+ 'yamaguchi' => array('abu' => array(),
3103
+ 'hagi' => array(),
3104
+ 'hikari' => array(),
3105
+ 'hofu' => array(),
3106
+ 'iwakuni' => array(),
3107
+ 'kudamatsu' => array(),
3108
+ 'mitou' => array(),
3109
+ 'nagato' => array(),
3110
+ 'oshima' => array(),
3111
+ 'shimonoseki' => array(),
3112
+ 'shunan' => array(),
3113
+ 'tabuse' => array(),
3114
+ 'tokuyama' => array(),
3115
+ 'toyota' => array(),
3116
+ 'ube' => array(),
3117
+ 'yuu' => array()),
3118
+ 'yamanashi' => array('chuo' => array(),
3119
+ 'doshi' => array(),
3120
+ 'fuefuki' => array(),
3121
+ 'fujikawa' => array(),
3122
+ 'fujikawaguchiko' => array(),
3123
+ 'fujiyoshida' => array(),
3124
+ 'hayakawa' => array(),
3125
+ 'hokuto' => array(),
3126
+ 'ichikawamisato' => array(),
3127
+ 'kai' => array(),
3128
+ 'kofu' => array(),
3129
+ 'koshu' => array(),
3130
+ 'kosuge' => array(),
3131
+ 'minami-alps' => array(),
3132
+ 'minobu' => array(),
3133
+ 'nakamichi' => array(),
3134
+ 'nanbu' => array(),
3135
+ 'narusawa' => array(),
3136
+ 'nirasaki' => array(),
3137
+ 'nishikatsura' => array(),
3138
+ 'oshino' => array(),
3139
+ 'otsuki' => array(),
3140
+ 'showa' => array(),
3141
+ 'tabayama' => array(),
3142
+ 'tsuru' => array(),
3143
+ 'uenohara' => array(),
3144
+ 'yamanakako' => array(),
3145
+ 'yamanashi' => array()),
3146
+ 'kawasaki' => array('*' => array(),
3147
+ 'city' => array('!' => '')),
3148
+ 'kitakyushu' => array('*' => array(),
3149
+ 'city' => array('!' => '')),
3150
+ 'kobe' => array('*' => array(),
3151
+ 'city' => array('!' => '')),
3152
+ 'nagoya' => array('*' => array(),
3153
+ 'city' => array('!' => '')),
3154
+ 'sapporo' => array('*' => array(),
3155
+ 'city' => array('!' => '')),
3156
+ 'sendai' => array('*' => array(),
3157
+ 'city' => array('!' => '')),
3158
+ 'yokohama' => array('*' => array(),
3159
+ 'city' => array('!' => '')),
3160
+ 'blogspot' => array()),
3161
+ 'ke' => array('*' => array()),
3162
+ 'kg' => array('org' => array(),
3163
+ 'net' => array(),
3164
+ 'com' => array(),
3165
+ 'edu' => array(),
3166
+ 'gov' => array(),
3167
+ 'mil' => array()),
3168
+ 'kh' => array('*' => array()),
3169
+ 'ki' => array('edu' => array(),
3170
+ 'biz' => array(),
3171
+ 'net' => array(),
3172
+ 'org' => array(),
3173
+ 'gov' => array(),
3174
+ 'info' => array(),
3175
+ 'com' => array()),
3176
+ 'km' => array('org' => array(),
3177
+ 'nom' => array(),
3178
+ 'gov' => array(),
3179
+ 'prd' => array(),
3180
+ 'tm' => array(),
3181
+ 'edu' => array(),
3182
+ 'mil' => array(),
3183
+ 'ass' => array(),
3184
+ 'com' => array(),
3185
+ 'coop' => array(),
3186
+ 'asso' => array(),
3187
+ 'presse' => array(),
3188
+ 'medecin' => array(),
3189
+ 'notaires' => array(),
3190
+ 'pharmaciens' => array(),
3191
+ 'veterinaire' => array(),
3192
+ 'gouv' => array()),
3193
+ 'kn' => array('net' => array(),
3194
+ 'org' => array(),
3195
+ 'edu' => array(),
3196
+ 'gov' => array()),
3197
+ 'kp' => array('com' => array(),
3198
+ 'edu' => array(),
3199
+ 'gov' => array(),
3200
+ 'org' => array(),
3201
+ 'rep' => array(),
3202
+ 'tra' => array()),
3203
+ 'kr' => array('ac' => array(),
3204
+ 'co' => array(),
3205
+ 'es' => array(),
3206
+ 'go' => array(),
3207
+ 'hs' => array(),
3208
+ 'kg' => array(),
3209
+ 'mil' => array(),
3210
+ 'ms' => array(),
3211
+ 'ne' => array(),
3212
+ 'or' => array(),
3213
+ 'pe' => array(),
3214
+ 're' => array(),
3215
+ 'sc' => array(),
3216
+ 'busan' => array(),
3217
+ 'chungbuk' => array(),
3218
+ 'chungnam' => array(),
3219
+ 'daegu' => array(),
3220
+ 'daejeon' => array(),
3221
+ 'gangwon' => array(),
3222
+ 'gwangju' => array(),
3223
+ 'gyeongbuk' => array(),
3224
+ 'gyeonggi' => array(),
3225
+ 'gyeongnam' => array(),
3226
+ 'incheon' => array(),
3227
+ 'jeju' => array(),
3228
+ 'jeonbuk' => array(),
3229
+ 'jeonnam' => array(),
3230
+ 'seoul' => array(),
3231
+ 'ulsan' => array(),
3232
+ 'blogspot' => array()),
3233
+ 'kw' => array('*' => array()),
3234
+ 'ky' => array('edu' => array(),
3235
+ 'gov' => array(),
3236
+ 'com' => array(),
3237
+ 'org' => array(),
3238
+ 'net' => array()),
3239
+ 'kz' => array('org' => array(),
3240
+ 'edu' => array(),
3241
+ 'net' => array(),
3242
+ 'gov' => array(),
3243
+ 'mil' => array(),
3244
+ 'com' => array()),
3245
+ 'la' => array('int' => array(),
3246
+ 'net' => array(),
3247
+ 'info' => array(),
3248
+ 'edu' => array(),
3249
+ 'gov' => array(),
3250
+ 'per' => array(),
3251
+ 'com' => array(),
3252
+ 'org' => array(),
3253
+ 'c' => array()),
3254
+ 'lb' => array('com' => array(),
3255
+ 'edu' => array(),
3256
+ 'gov' => array(),
3257
+ 'net' => array(),
3258
+ 'org' => array()),
3259
+ 'lc' => array('com' => array(),
3260
+ 'net' => array(),
3261
+ 'co' => array(),
3262
+ 'org' => array(),
3263
+ 'edu' => array(),
3264
+ 'gov' => array()),
3265
+ 'li' => array(),
3266
+ 'lk' => array('gov' => array(),
3267
+ 'sch' => array(),
3268
+ 'net' => array(),
3269
+ 'int' => array(),
3270
+ 'com' => array(),
3271
+ 'org' => array(),
3272
+ 'edu' => array(),
3273
+ 'ngo' => array(),
3274
+ 'soc' => array(),
3275
+ 'web' => array(),
3276
+ 'ltd' => array(),
3277
+ 'assn' => array(),
3278
+ 'grp' => array(),
3279
+ 'hotel' => array()),
3280
+ 'lr' => array('com' => array(),
3281
+ 'edu' => array(),
3282
+ 'gov' => array(),
3283
+ 'org' => array(),
3284
+ 'net' => array()),
3285
+ 'ls' => array('co' => array(),
3286
+ 'org' => array()),
3287
+ 'lt' => array('gov' => array()),
3288
+ 'lu' => array(),
3289
+ 'lv' => array('com' => array(),
3290
+ 'edu' => array(),
3291
+ 'gov' => array(),
3292
+ 'org' => array(),
3293
+ 'mil' => array(),
3294
+ 'id' => array(),
3295
+ 'net' => array(),
3296
+ 'asn' => array(),
3297
+ 'conf' => array()),
3298
+ 'ly' => array('com' => array(),
3299
+ 'net' => array(),
3300
+ 'gov' => array(),
3301
+ 'plc' => array(),
3302
+ 'edu' => array(),
3303
+ 'sch' => array(),
3304
+ 'med' => array(),
3305
+ 'org' => array(),
3306
+ 'id' => array()),
3307
+ 'ma' => array('co' => array(),
3308
+ 'net' => array(),
3309
+ 'gov' => array(),
3310
+ 'org' => array(),
3311
+ 'ac' => array(),
3312
+ 'press' => array()),
3313
+ 'mc' => array('tm' => array(),
3314
+ 'asso' => array()),
3315
+ 'md' => array(),
3316
+ 'me' => array('co' => array(),
3317
+ 'net' => array(),
3318
+ 'org' => array(),
3319
+ 'edu' => array(),
3320
+ 'ac' => array(),
3321
+ 'gov' => array(),
3322
+ 'its' => array(),
3323
+ 'priv' => array()),
3324
+ 'mg' => array('org' => array(),
3325
+ 'nom' => array(),
3326
+ 'gov' => array(),
3327
+ 'prd' => array(),
3328
+ 'tm' => array(),
3329
+ 'edu' => array(),
3330
+ 'mil' => array(),
3331
+ 'com' => array()),
3332
+ 'mh' => array(),
3333
+ 'mil' => array(),
3334
+ 'mk' => array('com' => array(),
3335
+ 'org' => array(),
3336
+ 'net' => array(),
3337
+ 'edu' => array(),
3338
+ 'gov' => array(),
3339
+ 'inf' => array(),
3340
+ 'name' => array()),
3341
+ 'ml' => array('com' => array(),
3342
+ 'edu' => array(),
3343
+ 'gouv' => array(),
3344
+ 'gov' => array(),
3345
+ 'net' => array(),
3346
+ 'org' => array(),
3347
+ 'presse' => array()),
3348
+ 'mm' => array('*' => array()),
3349
+ 'mn' => array('gov' => array(),
3350
+ 'edu' => array(),
3351
+ 'org' => array(),
3352
+ 'nyc' => array()),
3353
+ 'mo' => array('com' => array(),
3354
+ 'net' => array(),
3355
+ 'org' => array(),
3356
+ 'edu' => array(),
3357
+ 'gov' => array()),
3358
+ 'mobi' => array(),
3359
+ 'mp' => array(),
3360
+ 'mq' => array(),
3361
+ 'mr' => array('gov' => array(),
3362
+ 'blogspot' => array()),
3363
+ 'ms' => array('com' => array(),
3364
+ 'edu' => array(),
3365
+ 'gov' => array(),
3366
+ 'net' => array(),
3367
+ 'org' => array()),
3368
+ 'mt' => array('com' => array(),
3369
+ 'edu' => array(),
3370
+ 'net' => array(),
3371
+ 'org' => array()),
3372
+ 'mu' => array('com' => array(),
3373
+ 'net' => array(),
3374
+ 'org' => array(),
3375
+ 'gov' => array(),
3376
+ 'ac' => array(),
3377
+ 'co' => array(),
3378
+ 'or' => array()),
3379
+ 'museum' => array('academy' => array(),
3380
+ 'agriculture' => array(),
3381
+ 'air' => array(),
3382
+ 'airguard' => array(),
3383
+ 'alabama' => array(),
3384
+ 'alaska' => array(),
3385
+ 'amber' => array(),
3386
+ 'ambulance' => array(),
3387
+ 'american' => array(),
3388
+ 'americana' => array(),
3389
+ 'americanantiques' => array(),
3390
+ 'americanart' => array(),
3391
+ 'amsterdam' => array(),
3392
+ 'and' => array(),
3393
+ 'annefrank' => array(),
3394
+ 'anthro' => array(),
3395
+ 'anthropology' => array(),
3396
+ 'antiques' => array(),
3397
+ 'aquarium' => array(),
3398
+ 'arboretum' => array(),
3399
+ 'archaeological' => array(),
3400
+ 'archaeology' => array(),
3401
+ 'architecture' => array(),
3402
+ 'art' => array(),
3403
+ 'artanddesign' => array(),
3404
+ 'artcenter' => array(),
3405
+ 'artdeco' => array(),
3406
+ 'arteducation' => array(),
3407
+ 'artgallery' => array(),
3408
+ 'arts' => array(),
3409
+ 'artsandcrafts' => array(),
3410
+ 'asmatart' => array(),
3411
+ 'assassination' => array(),
3412
+ 'assisi' => array(),
3413
+ 'association' => array(),
3414
+ 'astronomy' => array(),
3415
+ 'atlanta' => array(),
3416
+ 'austin' => array(),
3417
+ 'australia' => array(),
3418
+ 'automotive' => array(),
3419
+ 'aviation' => array(),
3420
+ 'axis' => array(),
3421
+ 'badajoz' => array(),
3422
+ 'baghdad' => array(),
3423
+ 'bahn' => array(),
3424
+ 'bale' => array(),
3425
+ 'baltimore' => array(),
3426
+ 'barcelona' => array(),
3427
+ 'baseball' => array(),
3428
+ 'basel' => array(),
3429
+ 'baths' => array(),
3430
+ 'bauern' => array(),
3431
+ 'beauxarts' => array(),
3432
+ 'beeldengeluid' => array(),
3433
+ 'bellevue' => array(),
3434
+ 'bergbau' => array(),
3435
+ 'berkeley' => array(),
3436
+ 'berlin' => array(),
3437
+ 'bern' => array(),
3438
+ 'bible' => array(),
3439
+ 'bilbao' => array(),
3440
+ 'bill' => array(),
3441
+ 'birdart' => array(),
3442
+ 'birthplace' => array(),
3443
+ 'bonn' => array(),
3444
+ 'boston' => array(),
3445
+ 'botanical' => array(),
3446
+ 'botanicalgarden' => array(),
3447
+ 'botanicgarden' => array(),
3448
+ 'botany' => array(),
3449
+ 'brandywinevalley' => array(),
3450
+ 'brasil' => array(),
3451
+ 'bristol' => array(),
3452
+ 'british' => array(),
3453
+ 'britishcolumbia' => array(),
3454
+ 'broadcast' => array(),
3455
+ 'brunel' => array(),
3456
+ 'brussel' => array(),
3457
+ 'brussels' => array(),
3458
+ 'bruxelles' => array(),
3459
+ 'building' => array(),
3460
+ 'burghof' => array(),
3461
+ 'bus' => array(),
3462
+ 'bushey' => array(),
3463
+ 'cadaques' => array(),
3464
+ 'california' => array(),
3465
+ 'cambridge' => array(),
3466
+ 'can' => array(),
3467
+ 'canada' => array(),
3468
+ 'capebreton' => array(),
3469
+ 'carrier' => array(),
3470
+ 'cartoonart' => array(),
3471
+ 'casadelamoneda' => array(),
3472
+ 'castle' => array(),
3473
+ 'castres' => array(),
3474
+ 'celtic' => array(),
3475
+ 'center' => array(),
3476
+ 'chattanooga' => array(),
3477
+ 'cheltenham' => array(),
3478
+ 'chesapeakebay' => array(),
3479
+ 'chicago' => array(),
3480
+ 'children' => array(),
3481
+ 'childrens' => array(),
3482
+ 'childrensgarden' => array(),
3483
+ 'chiropractic' => array(),
3484
+ 'chocolate' => array(),
3485
+ 'christiansburg' => array(),
3486
+ 'cincinnati' => array(),
3487
+ 'cinema' => array(),
3488
+ 'circus' => array(),
3489
+ 'civilisation' => array(),
3490
+ 'civilization' => array(),
3491
+ 'civilwar' => array(),
3492
+ 'clinton' => array(),
3493
+ 'clock' => array(),
3494
+ 'coal' => array(),
3495
+ 'coastaldefence' => array(),
3496
+ 'cody' => array(),
3497
+ 'coldwar' => array(),
3498
+ 'collection' => array(),
3499
+ 'colonialwilliamsburg' => array(),
3500
+ 'coloradoplateau' => array(),
3501
+ 'columbia' => array(),
3502
+ 'columbus' => array(),
3503
+ 'communication' => array(),
3504
+ 'communications' => array(),
3505
+ 'community' => array(),
3506
+ 'computer' => array(),
3507
+ 'computerhistory' => array(),
3508
+ 'comunicações' => array(),
3509
+ 'contemporary' => array(),
3510
+ 'contemporaryart' => array(),
3511
+ 'convent' => array(),
3512
+ 'copenhagen' => array(),
3513
+ 'corporation' => array(),
3514
+ 'correios-e-telecomunicações' => array(),
3515
+ 'corvette' => array(),
3516
+ 'costume' => array(),
3517
+ 'countryestate' => array(),
3518
+ 'county' => array(),
3519
+ 'crafts' => array(),
3520
+ 'cranbrook' => array(),
3521
+ 'creation' => array(),
3522
+ 'cultural' => array(),
3523
+ 'culturalcenter' => array(),
3524
+ 'culture' => array(),
3525
+ 'cyber' => array(),
3526
+ 'cymru' => array(),
3527
+ 'dali' => array(),
3528
+ 'dallas' => array(),
3529
+ 'database' => array(),
3530
+ 'ddr' => array(),
3531
+ 'decorativearts' => array(),
3532
+ 'delaware' => array(),
3533
+ 'delmenhorst' => array(),
3534
+ 'denmark' => array(),
3535
+ 'depot' => array(),
3536
+ 'design' => array(),
3537
+ 'detroit' => array(),
3538
+ 'dinosaur' => array(),
3539
+ 'discovery' => array(),
3540
+ 'dolls' => array(),
3541
+ 'donostia' => array(),
3542
+ 'durham' => array(),
3543
+ 'eastafrica' => array(),
3544
+ 'eastcoast' => array(),
3545
+ 'education' => array(),
3546
+ 'educational' => array(),
3547
+ 'egyptian' => array(),
3548
+ 'eisenbahn' => array(),
3549
+ 'elburg' => array(),
3550
+ 'elvendrell' => array(),
3551
+ 'embroidery' => array(),
3552
+ 'encyclopedic' => array(),
3553
+ 'england' => array(),
3554
+ 'entomology' => array(),
3555
+ 'environment' => array(),
3556
+ 'environmentalconservation' => array(),
3557
+ 'epilepsy' => array(),
3558
+ 'essex' => array(),
3559
+ 'estate' => array(),
3560
+ 'ethnology' => array(),
3561
+ 'exeter' => array(),
3562
+ 'exhibition' => array(),
3563
+ 'family' => array(),
3564
+ 'farm' => array(),
3565
+ 'farmequipment' => array(),
3566
+ 'farmers' => array(),
3567
+ 'farmstead' => array(),
3568
+ 'field' => array(),
3569
+ 'figueres' => array(),
3570
+ 'filatelia' => array(),
3571
+ 'film' => array(),
3572
+ 'fineart' => array(),
3573
+ 'finearts' => array(),
3574
+ 'finland' => array(),
3575
+ 'flanders' => array(),
3576
+ 'florida' => array(),
3577
+ 'force' => array(),
3578
+ 'fortmissoula' => array(),
3579
+ 'fortworth' => array(),
3580
+ 'foundation' => array(),
3581
+ 'francaise' => array(),
3582
+ 'frankfurt' => array(),
3583
+ 'franziskaner' => array(),
3584
+ 'freemasonry' => array(),
3585
+ 'freiburg' => array(),
3586
+ 'fribourg' => array(),
3587
+ 'frog' => array(),
3588
+ 'fundacio' => array(),
3589
+ 'furniture' => array(),
3590
+ 'gallery' => array(),
3591
+ 'garden' => array(),
3592
+ 'gateway' => array(),
3593
+ 'geelvinck' => array(),
3594
+ 'gemological' => array(),
3595
+ 'geology' => array(),
3596
+ 'georgia' => array(),
3597
+ 'giessen' => array(),
3598
+ 'glas' => array(),
3599
+ 'glass' => array(),
3600
+ 'gorge' => array(),
3601
+ 'grandrapids' => array(),
3602
+ 'graz' => array(),
3603
+ 'guernsey' => array(),
3604
+ 'halloffame' => array(),
3605
+ 'hamburg' => array(),
3606
+ 'handson' => array(),
3607
+ 'harvestcelebration' => array(),
3608
+ 'hawaii' => array(),
3609
+ 'health' => array(),
3610
+ 'heimatunduhren' => array(),
3611
+ 'hellas' => array(),
3612
+ 'helsinki' => array(),
3613
+ 'hembygdsforbund' => array(),
3614
+ 'heritage' => array(),
3615
+ 'histoire' => array(),
3616
+ 'historical' => array(),
3617
+ 'historicalsociety' => array(),
3618
+ 'historichouses' => array(),
3619
+ 'historisch' => array(),
3620
+ 'historisches' => array(),
3621
+ 'history' => array(),
3622
+ 'historyofscience' => array(),
3623
+ 'horology' => array(),
3624
+ 'house' => array(),
3625
+ 'humanities' => array(),
3626
+ 'illustration' => array(),
3627
+ 'imageandsound' => array(),
3628
+ 'indian' => array(),
3629
+ 'indiana' => array(),
3630
+ 'indianapolis' => array(),
3631
+ 'indianmarket' => array(),
3632
+ 'intelligence' => array(),
3633
+ 'interactive' => array(),
3634
+ 'iraq' => array(),
3635
+ 'iron' => array(),
3636
+ 'isleofman' => array(),
3637
+ 'jamison' => array(),
3638
+ 'jefferson' => array(),
3639
+ 'jerusalem' => array(),
3640
+ 'jewelry' => array(),
3641
+ 'jewish' => array(),
3642
+ 'jewishart' => array(),
3643
+ 'jfk' => array(),
3644
+ 'journalism' => array(),
3645
+ 'judaica' => array(),
3646
+ 'judygarland' => array(),
3647
+ 'juedisches' => array(),
3648
+ 'juif' => array(),
3649
+ 'karate' => array(),
3650
+ 'karikatur' => array(),
3651
+ 'kids' => array(),
3652
+ 'koebenhavn' => array(),
3653
+ 'koeln' => array(),
3654
+ 'kunst' => array(),
3655
+ 'kunstsammlung' => array(),
3656
+ 'kunstunddesign' => array(),
3657
+ 'labor' => array(),
3658
+ 'labour' => array(),
3659
+ 'lajolla' => array(),
3660
+ 'lancashire' => array(),
3661
+ 'landes' => array(),
3662
+ 'lans' => array(),
3663
+ 'läns' => array(),
3664
+ 'larsson' => array(),
3665
+ 'lewismiller' => array(),
3666
+ 'lincoln' => array(),
3667
+ 'linz' => array(),
3668
+ 'living' => array(),
3669
+ 'livinghistory' => array(),
3670
+ 'localhistory' => array(),
3671
+ 'london' => array(),
3672
+ 'losangeles' => array(),
3673
+ 'louvre' => array(),
3674
+ 'loyalist' => array(),
3675
+ 'lucerne' => array(),
3676
+ 'luxembourg' => array(),
3677
+ 'luzern' => array(),
3678
+ 'mad' => array(),
3679
+ 'madrid' => array(),
3680
+ 'mallorca' => array(),
3681
+ 'manchester' => array(),
3682
+ 'mansion' => array(),
3683
+ 'mansions' => array(),
3684
+ 'manx' => array(),
3685
+ 'marburg' => array(),
3686
+ 'maritime' => array(),
3687
+ 'maritimo' => array(),
3688
+ 'maryland' => array(),
3689
+ 'marylhurst' => array(),
3690
+ 'media' => array(),
3691
+ 'medical' => array(),
3692
+ 'medizinhistorisches' => array(),
3693
+ 'meeres' => array(),
3694
+ 'memorial' => array(),
3695
+ 'mesaverde' => array(),
3696
+ 'michigan' => array(),
3697
+ 'midatlantic' => array(),
3698
+ 'military' => array(),
3699
+ 'mill' => array(),
3700
+ 'miners' => array(),
3701
+ 'mining' => array(),
3702
+ 'minnesota' => array(),
3703
+ 'missile' => array(),
3704
+ 'missoula' => array(),
3705
+ 'modern' => array(),
3706
+ 'moma' => array(),
3707
+ 'money' => array(),
3708
+ 'monmouth' => array(),
3709
+ 'monticello' => array(),
3710
+ 'montreal' => array(),
3711
+ 'moscow' => array(),
3712
+ 'motorcycle' => array(),
3713
+ 'muenchen' => array(),
3714
+ 'muenster' => array(),
3715
+ 'mulhouse' => array(),
3716
+ 'muncie' => array(),
3717
+ 'museet' => array(),
3718
+ 'museumcenter' => array(),
3719
+ 'museumvereniging' => array(),
3720
+ 'music' => array(),
3721
+ 'national' => array(),
3722
+ 'nationalfirearms' => array(),
3723
+ 'nationalheritage' => array(),
3724
+ 'nativeamerican' => array(),
3725
+ 'naturalhistory' => array(),
3726
+ 'naturalhistorymuseum' => array(),
3727
+ 'naturalsciences' => array(),
3728
+ 'nature' => array(),
3729
+ 'naturhistorisches' => array(),
3730
+ 'natuurwetenschappen' => array(),
3731
+ 'naumburg' => array(),
3732
+ 'naval' => array(),
3733
+ 'nebraska' => array(),
3734
+ 'neues' => array(),
3735
+ 'newhampshire' => array(),
3736
+ 'newjersey' => array(),
3737
+ 'newmexico' => array(),
3738
+ 'newport' => array(),
3739
+ 'newspaper' => array(),
3740
+ 'newyork' => array(),
3741
+ 'niepce' => array(),
3742
+ 'norfolk' => array(),
3743
+ 'north' => array(),
3744
+ 'nrw' => array(),
3745
+ 'nuernberg' => array(),
3746
+ 'nuremberg' => array(),
3747
+ 'nyc' => array(),
3748
+ 'nyny' => array(),
3749
+ 'oceanographic' => array(),
3750
+ 'oceanographique' => array(),
3751
+ 'omaha' => array(),
3752
+ 'online' => array(),
3753
+ 'ontario' => array(),
3754
+ 'openair' => array(),
3755
+ 'oregon' => array(),
3756
+ 'oregontrail' => array(),
3757
+ 'otago' => array(),
3758
+ 'oxford' => array(),
3759
+ 'pacific' => array(),
3760
+ 'paderborn' => array(),
3761
+ 'palace' => array(),
3762
+ 'paleo' => array(),
3763
+ 'palmsprings' => array(),
3764
+ 'panama' => array(),
3765
+ 'paris' => array(),
3766
+ 'pasadena' => array(),
3767
+ 'pharmacy' => array(),
3768
+ 'philadelphia' => array(),
3769
+ 'philadelphiaarea' => array(),
3770
+ 'philately' => array(),
3771
+ 'phoenix' => array(),
3772
+ 'photography' => array(),
3773
+ 'pilots' => array(),
3774
+ 'pittsburgh' => array(),
3775
+ 'planetarium' => array(),
3776
+ 'plantation' => array(),
3777
+ 'plants' => array(),
3778
+ 'plaza' => array(),
3779
+ 'portal' => array(),
3780
+ 'portland' => array(),
3781
+ 'portlligat' => array(),
3782
+ 'posts-and-telecommunications' => array(),
3783
+ 'preservation' => array(),
3784
+ 'presidio' => array(),
3785
+ 'press' => array(),
3786
+ 'project' => array(),
3787
+ 'public' => array(),
3788
+ 'pubol' => array(),
3789
+ 'quebec' => array(),
3790
+ 'railroad' => array(),
3791
+ 'railway' => array(),
3792
+ 'research' => array(),
3793
+ 'resistance' => array(),
3794
+ 'riodejaneiro' => array(),
3795
+ 'rochester' => array(),
3796
+ 'rockart' => array(),
3797
+ 'roma' => array(),
3798
+ 'russia' => array(),
3799
+ 'saintlouis' => array(),
3800
+ 'salem' => array(),
3801
+ 'salvadordali' => array(),
3802
+ 'salzburg' => array(),
3803
+ 'sandiego' => array(),
3804
+ 'sanfrancisco' => array(),
3805
+ 'santabarbara' => array(),
3806
+ 'santacruz' => array(),
3807
+ 'santafe' => array(),
3808
+ 'saskatchewan' => array(),
3809
+ 'satx' => array(),
3810
+ 'savannahga' => array(),
3811
+ 'schlesisches' => array(),
3812
+ 'schoenbrunn' => array(),
3813
+ 'schokoladen' => array(),
3814
+ 'school' => array(),
3815
+ 'schweiz' => array(),
3816
+ 'science' => array(),
3817
+ 'scienceandhistory' => array(),
3818
+ 'scienceandindustry' => array(),
3819
+ 'sciencecenter' => array(),
3820
+ 'sciencecenters' => array(),
3821
+ 'science-fiction' => array(),
3822
+ 'sciencehistory' => array(),
3823
+ 'sciences' => array(),
3824
+ 'sciencesnaturelles' => array(),
3825
+ 'scotland' => array(),
3826
+ 'seaport' => array(),
3827
+ 'settlement' => array(),
3828
+ 'settlers' => array(),
3829
+ 'shell' => array(),
3830
+ 'sherbrooke' => array(),
3831
+ 'sibenik' => array(),
3832
+ 'silk' => array(),
3833
+ 'ski' => array(),
3834
+ 'skole' => array(),
3835
+ 'society' => array(),
3836
+ 'sologne' => array(),
3837
+ 'soundandvision' => array(),
3838
+ 'southcarolina' => array(),
3839
+ 'southwest' => array(),
3840
+ 'space' => array(),
3841
+ 'spy' => array(),
3842
+ 'square' => array(),
3843
+ 'stadt' => array(),
3844
+ 'stalbans' => array(),
3845
+ 'starnberg' => array(),
3846
+ 'state' => array(),
3847
+ 'stateofdelaware' => array(),
3848
+ 'station' => array(),
3849
+ 'steam' => array(),
3850
+ 'steiermark' => array(),
3851
+ 'stjohn' => array(),
3852
+ 'stockholm' => array(),
3853
+ 'stpetersburg' => array(),
3854
+ 'stuttgart' => array(),
3855
+ 'suisse' => array(),
3856
+ 'surgeonshall' => array(),
3857
+ 'surrey' => array(),
3858
+ 'svizzera' => array(),
3859
+ 'sweden' => array(),
3860
+ 'sydney' => array(),
3861
+ 'tank' => array(),
3862
+ 'tcm' => array(),
3863
+ 'technology' => array(),
3864
+ 'telekommunikation' => array(),
3865
+ 'television' => array(),
3866
+ 'texas' => array(),
3867
+ 'textile' => array(),
3868
+ 'theater' => array(),
3869
+ 'time' => array(),
3870
+ 'timekeeping' => array(),
3871
+ 'topology' => array(),
3872
+ 'torino' => array(),
3873
+ 'touch' => array(),
3874
+ 'town' => array(),
3875
+ 'transport' => array(),
3876
+ 'tree' => array(),
3877
+ 'trolley' => array(),
3878
+ 'trust' => array(),
3879
+ 'trustee' => array(),
3880
+ 'uhren' => array(),
3881
+ 'ulm' => array(),
3882
+ 'undersea' => array(),
3883
+ 'university' => array(),
3884
+ 'usa' => array(),
3885
+ 'usantiques' => array(),
3886
+ 'usarts' => array(),
3887
+ 'uscountryestate' => array(),
3888
+ 'usculture' => array(),
3889
+ 'usdecorativearts' => array(),
3890
+ 'usgarden' => array(),
3891
+ 'ushistory' => array(),
3892
+ 'ushuaia' => array(),
3893
+ 'uslivinghistory' => array(),
3894
+ 'utah' => array(),
3895
+ 'uvic' => array(),
3896
+ 'valley' => array(),
3897
+ 'vantaa' => array(),
3898
+ 'versailles' => array(),
3899
+ 'viking' => array(),
3900
+ 'village' => array(),
3901
+ 'virginia' => array(),
3902
+ 'virtual' => array(),
3903
+ 'virtuel' => array(),
3904
+ 'vlaanderen' => array(),
3905
+ 'volkenkunde' => array(),
3906
+ 'wales' => array(),
3907
+ 'wallonie' => array(),
3908
+ 'war' => array(),
3909
+ 'washingtondc' => array(),
3910
+ 'watchandclock' => array(),
3911
+ 'watch-and-clock' => array(),
3912
+ 'western' => array(),
3913
+ 'westfalen' => array(),
3914
+ 'whaling' => array(),
3915
+ 'wildlife' => array(),
3916
+ 'williamsburg' => array(),
3917
+ 'windmill' => array(),
3918
+ 'workshop' => array(),
3919
+ 'york' => array(),
3920
+ 'yorkshire' => array(),
3921
+ 'yosemite' => array(),
3922
+ 'youth' => array(),
3923
+ 'zoological' => array(),
3924
+ 'zoology' => array(),
3925
+ 'ירושלים' => array(),
3926
+ 'иком' => array()),
3927
+ 'mv' => array('aero' => array(),
3928
+ 'biz' => array(),
3929
+ 'com' => array(),
3930
+ 'coop' => array(),
3931
+ 'edu' => array(),
3932
+ 'gov' => array(),
3933
+ 'info' => array(),
3934
+ 'int' => array(),
3935
+ 'mil' => array(),
3936
+ 'museum' => array(),
3937
+ 'name' => array(),
3938
+ 'net' => array(),
3939
+ 'org' => array(),
3940
+ 'pro' => array()),
3941
+ 'mw' => array('ac' => array(),
3942
+ 'biz' => array(),
3943
+ 'co' => array(),
3944
+ 'com' => array(),
3945
+ 'coop' => array(),
3946
+ 'edu' => array(),
3947
+ 'gov' => array(),
3948
+ 'int' => array(),
3949
+ 'museum' => array(),
3950
+ 'net' => array(),
3951
+ 'org' => array()),
3952
+ 'mx' => array('com' => array(),
3953
+ 'org' => array(),
3954
+ 'gob' => array(),
3955
+ 'edu' => array(),
3956
+ 'net' => array(),
3957
+ 'blogspot' => array()),
3958
+ 'my' => array('com' => array(),
3959
+ 'net' => array(),
3960
+ 'org' => array(),
3961
+ 'gov' => array(),
3962
+ 'edu' => array(),
3963
+ 'mil' => array(),
3964
+ 'name' => array()),
3965
+ 'mz' => array('*' => array(),
3966
+ 'teledata' => array('!' => '')),
3967
+ 'na' => array('info' => array(),
3968
+ 'pro' => array(),
3969
+ 'name' => array(),
3970
+ 'school' => array(),
3971
+ 'or' => array(),
3972
+ 'dr' => array(),
3973
+ 'us' => array(),
3974
+ 'mx' => array(),
3975
+ 'ca' => array(),
3976
+ 'in' => array(),
3977
+ 'cc' => array(),
3978
+ 'tv' => array(),
3979
+ 'ws' => array(),
3980
+ 'mobi' => array(),
3981
+ 'co' => array(),
3982
+ 'com' => array(),
3983
+ 'org' => array()),
3984
+ 'name' => array('her' => array('forgot' => array()),
3985
+ 'his' => array('forgot' => array())),
3986
+ 'nc' => array('asso' => array()),
3987
+ 'ne' => array(),
3988
+ 'net' => array('cloudfront' => array(),
3989
+ 'gb' => array(),
3990
+ 'hu' => array(),
3991
+ 'jp' => array(),
3992
+ 'se' => array(),
3993
+ 'uk' => array(),
3994
+ 'in' => array(),
3995
+ 'at-band-camp' => array(),
3996
+ 'blogdns' => array(),
3997
+ 'broke-it' => array(),
3998
+ 'buyshouses' => array(),
3999
+ 'dnsalias' => array(),
4000
+ 'dnsdojo' => array(),
4001
+ 'does-it' => array(),
4002
+ 'dontexist' => array(),
4003
+ 'dynalias' => array(),
4004
+ 'dynathome' => array(),
4005
+ 'endofinternet' => array(),
4006
+ 'from-az' => array(),
4007
+ 'from-co' => array(),
4008
+ 'from-la' => array(),
4009
+ 'from-ny' => array(),
4010
+ 'gets-it' => array(),
4011
+ 'ham-radio-op' => array(),
4012
+ 'homeftp' => array(),
4013
+ 'homeip' => array(),
4014
+ 'homelinux' => array(),
4015
+ 'homeunix' => array(),
4016
+ 'in-the-band' => array(),
4017
+ 'is-a-chef' => array(),
4018
+ 'is-a-geek' => array(),
4019
+ 'isa-geek' => array(),
4020
+ 'kicks-ass' => array(),
4021
+ 'office-on-the' => array(),
4022
+ 'podzone' => array(),
4023
+ 'scrapper-site' => array(),
4024
+ 'selfip' => array(),
4025
+ 'sells-it' => array(),
4026
+ 'servebbs' => array(),
4027
+ 'serveftp' => array(),
4028
+ 'thruhere' => array(),
4029
+ 'webhop' => array(),
4030
+ 'fastly' => array('ssl' => array('a' => array(),
4031
+ 'b' => array(),
4032
+ 'global' => array()),
4033
+ 'prod' => array('a' => array(),
4034
+ 'global' => array())),
4035
+ 'azurewebsites' => array(),
4036
+ 'azure-mobile' => array(),
4037
+ 'cloudapp' => array(),
4038
+ 'za' => array()),
4039
+ 'nf' => array('com' => array(),
4040
+ 'net' => array(),
4041
+ 'per' => array(),
4042
+ 'rec' => array(),
4043
+ 'web' => array(),
4044
+ 'arts' => array(),
4045
+ 'firm' => array(),
4046
+ 'info' => array(),
4047
+ 'other' => array(),
4048
+ 'store' => array()),
4049
+ 'ng' => array('com' => array(),
4050
+ 'edu' => array(),
4051
+ 'name' => array(),
4052
+ 'net' => array(),
4053
+ 'org' => array(),
4054
+ 'sch' => array(),
4055
+ 'gov' => array(),
4056
+ 'mil' => array(),
4057
+ 'mobi' => array()),
4058
+ 'ni' => array('*' => array()),
4059
+ 'nl' => array('bv' => array(),
4060
+ 'co' => array(),
4061
+ 'blogspot' => array()),
4062
+ 'no' => array('fhs' => array(),
4063
+ 'vgs' => array(),
4064
+ 'fylkesbibl' => array(),
4065
+ 'folkebibl' => array(),
4066
+ 'museum' => array(),
4067
+ 'idrett' => array(),
4068
+ 'priv' => array(),
4069
+ 'mil' => array(),
4070
+ 'stat' => array(),
4071
+ 'dep' => array(),
4072
+ 'kommune' => array(),
4073
+ 'herad' => array(),
4074
+ 'aa' => array('gs' => array()),
4075
+ 'ah' => array('gs' => array()),
4076
+ 'bu' => array('gs' => array()),
4077
+ 'fm' => array('gs' => array()),
4078
+ 'hl' => array('gs' => array()),
4079
+ 'hm' => array('gs' => array()),
4080
+ 'jan-mayen' => array('gs' => array()),
4081
+ 'mr' => array('gs' => array()),
4082
+ 'nl' => array('gs' => array()),
4083
+ 'nt' => array('gs' => array()),
4084
+ 'of' => array('gs' => array()),
4085
+ 'ol' => array('gs' => array()),
4086
+ 'oslo' => array('gs' => array()),
4087
+ 'rl' => array('gs' => array()),
4088
+ 'sf' => array('gs' => array()),
4089
+ 'st' => array('gs' => array()),
4090
+ 'svalbard' => array('gs' => array()),
4091
+ 'tm' => array('gs' => array()),
4092
+ 'tr' => array('gs' => array()),
4093
+ 'va' => array('gs' => array()),
4094
+ 'vf' => array('gs' => array()),
4095
+ 'akrehamn' => array(),
4096
+ 'åkrehamn' => array(),
4097
+ 'algard' => array(),
4098
+ 'ålgård' => array(),
4099
+ 'arna' => array(),
4100
+ 'brumunddal' => array(),
4101
+ 'bryne' => array(),
4102
+ 'bronnoysund' => array(),
4103
+ 'brønnøysund' => array(),
4104
+ 'drobak' => array(),
4105
+ 'drøbak' => array(),
4106
+ 'egersund' => array(),
4107
+ 'fetsund' => array(),
4108
+ 'floro' => array(),
4109
+ 'florø' => array(),
4110
+ 'fredrikstad' => array(),
4111
+ 'hokksund' => array(),
4112
+ 'honefoss' => array(),
4113
+ 'hønefoss' => array(),
4114
+ 'jessheim' => array(),
4115
+ 'jorpeland' => array(),
4116
+ 'jørpeland' => array(),
4117
+ 'kirkenes' => array(),
4118
+ 'kopervik' => array(),
4119
+ 'krokstadelva' => array(),
4120
+ 'langevag' => array(),
4121
+ 'langevåg' => array(),
4122
+ 'leirvik' => array(),
4123
+ 'mjondalen' => array(),
4124
+ 'mjøndalen' => array(),
4125
+ 'mo-i-rana' => array(),
4126
+ 'mosjoen' => array(),
4127
+ 'mosjøen' => array(),
4128
+ 'nesoddtangen' => array(),
4129
+ 'orkanger' => array(),
4130
+ 'osoyro' => array(),
4131
+ 'osøyro' => array(),
4132
+ 'raholt' => array(),
4133
+ 'råholt' => array(),
4134
+ 'sandnessjoen' => array(),
4135
+ 'sandnessjøen' => array(),
4136
+ 'skedsmokorset' => array(),
4137
+ 'slattum' => array(),
4138
+ 'spjelkavik' => array(),
4139
+ 'stathelle' => array(),
4140
+ 'stavern' => array(),
4141
+ 'stjordalshalsen' => array(),
4142
+ 'stjørdalshalsen' => array(),
4143
+ 'tananger' => array(),
4144
+ 'tranby' => array(),
4145
+ 'vossevangen' => array(),
4146
+ 'afjord' => array(),
4147
+ 'åfjord' => array(),
4148
+ 'agdenes' => array(),
4149
+ 'al' => array(),
4150
+ 'ål' => array(),
4151
+ 'alesund' => array(),
4152
+ 'ålesund' => array(),
4153
+ 'alstahaug' => array(),
4154
+ 'alta' => array(),
4155
+ 'áltá' => array(),
4156
+ 'alaheadju' => array(),
4157
+ 'álaheadju' => array(),
4158
+ 'alvdal' => array(),
4159
+ 'amli' => array(),
4160
+ 'åmli' => array(),
4161
+ 'amot' => array(),
4162
+ 'åmot' => array(),
4163
+ 'andebu' => array(),
4164
+ 'andoy' => array(),
4165
+ 'andøy' => array(),
4166
+ 'andasuolo' => array(),
4167
+ 'ardal' => array(),
4168
+ 'årdal' => array(),
4169
+ 'aremark' => array(),
4170
+ 'arendal' => array(),
4171
+ 'ås' => array(),
4172
+ 'aseral' => array(),
4173
+ 'åseral' => array(),
4174
+ 'asker' => array(),
4175
+ 'askim' => array(),
4176
+ 'askvoll' => array(),
4177
+ 'askoy' => array(),
4178
+ 'askøy' => array(),
4179
+ 'asnes' => array(),
4180
+ 'åsnes' => array(),
4181
+ 'audnedaln' => array(),
4182
+ 'aukra' => array(),
4183
+ 'aure' => array(),
4184
+ 'aurland' => array(),
4185
+ 'aurskog-holand' => array(),
4186
+ 'aurskog-høland' => array(),
4187
+ 'austevoll' => array(),
4188
+ 'austrheim' => array(),
4189
+ 'averoy' => array(),
4190
+ 'averøy' => array(),
4191
+ 'balestrand' => array(),
4192
+ 'ballangen' => array(),
4193
+ 'balat' => array(),
4194
+ 'bálát' => array(),
4195
+ 'balsfjord' => array(),
4196
+ 'bahccavuotna' => array(),
4197
+ 'báhccavuotna' => array(),
4198
+ 'bamble' => array(),
4199
+ 'bardu' => array(),
4200
+ 'beardu' => array(),
4201
+ 'beiarn' => array(),
4202
+ 'bajddar' => array(),
4203
+ 'bájddar' => array(),
4204
+ 'baidar' => array(),
4205
+ 'báidár' => array(),
4206
+ 'berg' => array(),
4207
+ 'bergen' => array(),
4208
+ 'berlevag' => array(),
4209
+ 'berlevåg' => array(),
4210
+ 'bearalvahki' => array(),
4211
+ 'bearalváhki' => array(),
4212
+ 'bindal' => array(),
4213
+ 'birkenes' => array(),
4214
+ 'bjarkoy' => array(),
4215
+ 'bjarkøy' => array(),
4216
+ 'bjerkreim' => array(),
4217
+ 'bjugn' => array(),
4218
+ 'bodo' => array(),
4219
+ 'bodø' => array(),
4220
+ 'badaddja' => array(),
4221
+ 'bådåddjå' => array(),
4222
+ 'budejju' => array(),
4223
+ 'bokn' => array(),
4224
+ 'bremanger' => array(),
4225
+ 'bronnoy' => array(),
4226
+ 'brønnøy' => array(),
4227
+ 'bygland' => array(),
4228
+ 'bykle' => array(),
4229
+ 'barum' => array(),
4230
+ 'bærum' => array(),
4231
+ 'telemark' => array('bo' => array(),
4232
+ 'bø' => array()),
4233
+ 'nordland' => array('bo' => array(),
4234
+ 'bø' => array(),
4235
+ 'heroy' => array(),
4236
+ 'herøy' => array()),
4237
+ 'bievat' => array(),
4238
+ 'bievát' => array(),
4239
+ 'bomlo' => array(),
4240
+ 'bømlo' => array(),
4241
+ 'batsfjord' => array(),
4242
+ 'båtsfjord' => array(),
4243
+ 'bahcavuotna' => array(),
4244
+ 'báhcavuotna' => array(),
4245
+ 'dovre' => array(),
4246
+ 'drammen' => array(),
4247
+ 'drangedal' => array(),
4248
+ 'dyroy' => array(),
4249
+ 'dyrøy' => array(),
4250
+ 'donna' => array(),
4251
+ 'dønna' => array(),
4252
+ 'eid' => array(),
4253
+ 'eidfjord' => array(),
4254
+ 'eidsberg' => array(),
4255
+ 'eidskog' => array(),
4256
+ 'eidsvoll' => array(),
4257
+ 'eigersund' => array(),
4258
+ 'elverum' => array(),
4259
+ 'enebakk' => array(),
4260
+ 'engerdal' => array(),
4261
+ 'etne' => array(),
4262
+ 'etnedal' => array(),
4263
+ 'evenes' => array(),
4264
+ 'evenassi' => array(),
4265
+ 'evenášši' => array(),
4266
+ 'evje-og-hornnes' => array(),
4267
+ 'farsund' => array(),
4268
+ 'fauske' => array(),
4269
+ 'fuossko' => array(),
4270
+ 'fuoisku' => array(),
4271
+ 'fedje' => array(),
4272
+ 'fet' => array(),
4273
+ 'finnoy' => array(),
4274
+ 'finnøy' => array(),
4275
+ 'fitjar' => array(),
4276
+ 'fjaler' => array(),
4277
+ 'fjell' => array(),
4278
+ 'flakstad' => array(),
4279
+ 'flatanger' => array(),
4280
+ 'flekkefjord' => array(),
4281
+ 'flesberg' => array(),
4282
+ 'flora' => array(),
4283
+ 'fla' => array(),
4284
+ 'flå' => array(),
4285
+ 'folldal' => array(),
4286
+ 'forsand' => array(),
4287
+ 'fosnes' => array(),
4288
+ 'frei' => array(),
4289
+ 'frogn' => array(),
4290
+ 'froland' => array(),
4291
+ 'frosta' => array(),
4292
+ 'frana' => array(),
4293
+ 'fræna' => array(),
4294
+ 'froya' => array(),
4295
+ 'frøya' => array(),
4296
+ 'fusa' => array(),
4297
+ 'fyresdal' => array(),
4298
+ 'forde' => array(),
4299
+ 'førde' => array(),
4300
+ 'gamvik' => array(),
4301
+ 'gangaviika' => array(),
4302
+ 'gáŋgaviika' => array(),
4303
+ 'gaular' => array(),
4304
+ 'gausdal' => array(),
4305
+ 'gildeskal' => array(),
4306
+ 'gildeskål' => array(),
4307
+ 'giske' => array(),
4308
+ 'gjemnes' => array(),
4309
+ 'gjerdrum' => array(),
4310
+ 'gjerstad' => array(),
4311
+ 'gjesdal' => array(),
4312
+ 'gjovik' => array(),
4313
+ 'gjøvik' => array(),
4314
+ 'gloppen' => array(),
4315
+ 'gol' => array(),
4316
+ 'gran' => array(),
4317
+ 'grane' => array(),
4318
+ 'granvin' => array(),
4319
+ 'gratangen' => array(),
4320
+ 'grimstad' => array(),
4321
+ 'grong' => array(),
4322
+ 'kraanghke' => array(),
4323
+ 'kråanghke' => array(),
4324
+ 'grue' => array(),
4325
+ 'gulen' => array(),
4326
+ 'hadsel' => array(),
4327
+ 'halden' => array(),
4328
+ 'halsa' => array(),
4329
+ 'hamar' => array(),
4330
+ 'hamaroy' => array(),
4331
+ 'habmer' => array(),
4332
+ 'hábmer' => array(),
4333
+ 'hapmir' => array(),
4334
+ 'hápmir' => array(),
4335
+ 'hammerfest' => array(),
4336
+ 'hammarfeasta' => array(),
4337
+ 'hámmárfeasta' => array(),
4338
+ 'haram' => array(),
4339
+ 'hareid' => array(),
4340
+ 'harstad' => array(),
4341
+ 'hasvik' => array(),
4342
+ 'aknoluokta' => array(),
4343
+ 'ákŋoluokta' => array(),
4344
+ 'hattfjelldal' => array(),
4345
+ 'aarborte' => array(),
4346
+ 'haugesund' => array(),
4347
+ 'hemne' => array(),
4348
+ 'hemnes' => array(),
4349
+ 'hemsedal' => array(),
4350
+ 'more-og-romsdal' => array('heroy' => array(),
4351
+ 'sande' => array()),
4352
+ 'møre-og-romsdal' => array('herøy' => array(),
4353
+ 'sande' => array()),
4354
+ 'hitra' => array(),
4355
+ 'hjartdal' => array(),
4356
+ 'hjelmeland' => array(),
4357
+ 'hobol' => array(),
4358
+ 'hobøl' => array(),
4359
+ 'hof' => array(),
4360
+ 'hol' => array(),
4361
+ 'hole' => array(),
4362
+ 'holmestrand' => array(),
4363
+ 'holtalen' => array(),
4364
+ 'holtålen' => array(),
4365
+ 'hornindal' => array(),
4366
+ 'horten' => array(),
4367
+ 'hurdal' => array(),
4368
+ 'hurum' => array(),
4369
+ 'hvaler' => array(),
4370
+ 'hyllestad' => array(),
4371
+ 'hagebostad' => array(),
4372
+ 'hægebostad' => array(),
4373
+ 'hoyanger' => array(),
4374
+ 'høyanger' => array(),
4375
+ 'hoylandet' => array(),
4376
+ 'høylandet' => array(),
4377
+ 'ha' => array(),
4378
+ 'hå' => array(),
4379
+ 'ibestad' => array(),
4380
+ 'inderoy' => array(),
4381
+ 'inderøy' => array(),
4382
+ 'iveland' => array(),
4383
+ 'jevnaker' => array(),
4384
+ 'jondal' => array(),
4385
+ 'jolster' => array(),
4386
+ 'jølster' => array(),
4387
+ 'karasjok' => array(),
4388
+ 'karasjohka' => array(),
4389
+ 'kárášjohka' => array(),
4390
+ 'karlsoy' => array(),
4391
+ 'galsa' => array(),
4392
+ 'gálsá' => array(),
4393
+ 'karmoy' => array(),
4394
+ 'karmøy' => array(),
4395
+ 'kautokeino' => array(),
4396
+ 'guovdageaidnu' => array(),
4397
+ 'klepp' => array(),
4398
+ 'klabu' => array(),
4399
+ 'klæbu' => array(),
4400
+ 'kongsberg' => array(),
4401
+ 'kongsvinger' => array(),
4402
+ 'kragero' => array(),
4403
+ 'kragerø' => array(),
4404
+ 'kristiansand' => array(),
4405
+ 'kristiansund' => array(),
4406
+ 'krodsherad' => array(),
4407
+ 'krødsherad' => array(),
4408
+ 'kvalsund' => array(),
4409
+ 'rahkkeravju' => array(),
4410
+ 'ráhkkerávju' => array(),
4411
+ 'kvam' => array(),
4412
+ 'kvinesdal' => array(),
4413
+ 'kvinnherad' => array(),
4414
+ 'kviteseid' => array(),
4415
+ 'kvitsoy' => array(),
4416
+ 'kvitsøy' => array(),
4417
+ 'kvafjord' => array(),
4418
+ 'kvæfjord' => array(),
4419
+ 'giehtavuoatna' => array(),
4420
+ 'kvanangen' => array(),
4421
+ 'kvænangen' => array(),
4422
+ 'navuotna' => array(),
4423
+ 'návuotna' => array(),
4424
+ 'kafjord' => array(),
4425
+ 'kåfjord' => array(),
4426
+ 'gaivuotna' => array(),
4427
+ 'gáivuotna' => array(),
4428
+ 'larvik' => array(),
4429
+ 'lavangen' => array(),
4430
+ 'lavagis' => array(),
4431
+ 'loabat' => array(),
4432
+ 'loabát' => array(),
4433
+ 'lebesby' => array(),
4434
+ 'davvesiida' => array(),
4435
+ 'leikanger' => array(),
4436
+ 'leirfjord' => array(),
4437
+ 'leka' => array(),
4438
+ 'leksvik' => array(),
4439
+ 'lenvik' => array(),
4440
+ 'leangaviika' => array(),
4441
+ 'leaŋgaviika' => array(),
4442
+ 'lesja' => array(),
4443
+ 'levanger' => array(),
4444
+ 'lier' => array(),
4445
+ 'lierne' => array(),
4446
+ 'lillehammer' => array(),
4447
+ 'lillesand' => array(),
4448
+ 'lindesnes' => array(),
4449
+ 'lindas' => array(),
4450
+ 'lindås' => array(),
4451
+ 'lom' => array(),
4452
+ 'loppa' => array(),
4453
+ 'lahppi' => array(),
4454
+ 'láhppi' => array(),
4455
+ 'lund' => array(),
4456
+ 'lunner' => array(),
4457
+ 'luroy' => array(),
4458
+ 'lurøy' => array(),
4459
+ 'luster' => array(),
4460
+ 'lyngdal' => array(),
4461
+ 'lyngen' => array(),
4462
+ 'ivgu' => array(),
4463
+ 'lardal' => array(),
4464
+ 'lerdal' => array(),
4465
+ 'lærdal' => array(),
4466
+ 'lodingen' => array(),
4467
+ 'lødingen' => array(),
4468
+ 'lorenskog' => array(),
4469
+ 'lørenskog' => array(),
4470
+ 'loten' => array(),
4471
+ 'løten' => array(),
4472
+ 'malvik' => array(),
4473
+ 'masoy' => array(),
4474
+ 'måsøy' => array(),
4475
+ 'muosat' => array(),
4476
+ 'muosát' => array(),
4477
+ 'mandal' => array(),
4478
+ 'marker' => array(),
4479
+ 'marnardal' => array(),
4480
+ 'masfjorden' => array(),
4481
+ 'meland' => array(),
4482
+ 'meldal' => array(),
4483
+ 'melhus' => array(),
4484
+ 'meloy' => array(),
4485
+ 'meløy' => array(),
4486
+ 'meraker' => array(),
4487
+ 'meråker' => array(),
4488
+ 'moareke' => array(),
4489
+ 'moåreke' => array(),
4490
+ 'midsund' => array(),
4491
+ 'midtre-gauldal' => array(),
4492
+ 'modalen' => array(),
4493
+ 'modum' => array(),
4494
+ 'molde' => array(),
4495
+ 'moskenes' => array(),
4496
+ 'moss' => array(),
4497
+ 'mosvik' => array(),
4498
+ 'malselv' => array(),
4499
+ 'målselv' => array(),
4500
+ 'malatvuopmi' => array(),
4501
+ 'málatvuopmi' => array(),
4502
+ 'namdalseid' => array(),
4503
+ 'aejrie' => array(),
4504
+ 'namsos' => array(),
4505
+ 'namsskogan' => array(),
4506
+ 'naamesjevuemie' => array(),
4507
+ 'nååmesjevuemie' => array(),
4508
+ 'laakesvuemie' => array(),
4509
+ 'nannestad' => array(),
4510
+ 'narvik' => array(),
4511
+ 'narviika' => array(),
4512
+ 'naustdal' => array(),
4513
+ 'nedre-eiker' => array(),
4514
+ 'akershus' => array('nes' => array()),
4515
+ 'buskerud' => array('nes' => array()),
4516
+ 'nesna' => array(),
4517
+ 'nesodden' => array(),
4518
+ 'nesseby' => array(),
4519
+ 'unjarga' => array(),
4520
+ 'unjárga' => array(),
4521
+ 'nesset' => array(),
4522
+ 'nissedal' => array(),
4523
+ 'nittedal' => array(),
4524
+ 'nord-aurdal' => array(),
4525
+ 'nord-fron' => array(),
4526
+ 'nord-odal' => array(),
4527
+ 'norddal' => array(),
4528
+ 'nordkapp' => array(),
4529
+ 'davvenjarga' => array(),
4530
+ 'davvenjárga' => array(),
4531
+ 'nordre-land' => array(),
4532
+ 'nordreisa' => array(),
4533
+ 'raisa' => array(),
4534
+ 'ráisa' => array(),
4535
+ 'nore-og-uvdal' => array(),
4536
+ 'notodden' => array(),
4537
+ 'naroy' => array(),
4538
+ 'nærøy' => array(),
4539
+ 'notteroy' => array(),
4540
+ 'nøtterøy' => array(),
4541
+ 'odda' => array(),
4542
+ 'oksnes' => array(),
4543
+ 'øksnes' => array(),
4544
+ 'oppdal' => array(),
4545
+ 'oppegard' => array(),
4546
+ 'oppegård' => array(),
4547
+ 'orkdal' => array(),
4548
+ 'orland' => array(),
4549
+ 'ørland' => array(),
4550
+ 'orskog' => array(),
4551
+ 'ørskog' => array(),
4552
+ 'orsta' => array(),
4553
+ 'ørsta' => array(),
4554
+ 'hedmark' => array('os' => array(),
4555
+ 'valer' => array(),
4556
+ 'våler' => array()),
4557
+ 'hordaland' => array('os' => array()),
4558
+ 'osen' => array(),
4559
+ 'osteroy' => array(),
4560
+ 'osterøy' => array(),
4561
+ 'ostre-toten' => array(),
4562
+ 'østre-toten' => array(),
4563
+ 'overhalla' => array(),
4564
+ 'ovre-eiker' => array(),
4565
+ 'øvre-eiker' => array(),
4566
+ 'oyer' => array(),
4567
+ 'øyer' => array(),
4568
+ 'oygarden' => array(),
4569
+ 'øygarden' => array(),
4570
+ 'oystre-slidre' => array(),
4571
+ 'øystre-slidre' => array(),
4572
+ 'porsanger' => array(),
4573
+ 'porsangu' => array(),
4574
+ 'porsáŋgu' => array(),
4575
+ 'porsgrunn' => array(),
4576
+ 'radoy' => array(),
4577
+ 'radøy' => array(),
4578
+ 'rakkestad' => array(),
4579
+ 'rana' => array(),
4580
+ 'ruovat' => array(),
4581
+ 'randaberg' => array(),
4582
+ 'rauma' => array(),
4583
+ 'rendalen' => array(),
4584
+ 'rennebu' => array(),
4585
+ 'rennesoy' => array(),
4586
+ 'rennesøy' => array(),
4587
+ 'rindal' => array(),
4588
+ 'ringebu' => array(),
4589
+ 'ringerike' => array(),
4590
+ 'ringsaker' => array(),
4591
+ 'rissa' => array(),
4592
+ 'risor' => array(),
4593
+ 'risør' => array(),
4594
+ 'roan' => array(),
4595
+ 'rollag' => array(),
4596
+ 'rygge' => array(),
4597
+ 'ralingen' => array(),
4598
+ 'rælingen' => array(),
4599
+ 'rodoy' => array(),
4600
+ 'rødøy' => array(),
4601
+ 'romskog' => array(),
4602
+ 'rømskog' => array(),
4603
+ 'roros' => array(),
4604
+ 'røros' => array(),
4605
+ 'rost' => array(),
4606
+ 'røst' => array(),
4607
+ 'royken' => array(),
4608
+ 'røyken' => array(),
4609
+ 'royrvik' => array(),
4610
+ 'røyrvik' => array(),
4611
+ 'rade' => array(),
4612
+ 'råde' => array(),
4613
+ 'salangen' => array(),
4614
+ 'siellak' => array(),
4615
+ 'saltdal' => array(),
4616
+ 'salat' => array(),
4617
+ 'sálát' => array(),
4618
+ 'sálat' => array(),
4619
+ 'samnanger' => array(),
4620
+ 'vestfold' => array('sande' => array()),
4621
+ 'sandefjord' => array(),
4622
+ 'sandnes' => array(),
4623
+ 'sandoy' => array(),
4624
+ 'sandøy' => array(),
4625
+ 'sarpsborg' => array(),
4626
+ 'sauda' => array(),
4627
+ 'sauherad' => array(),
4628
+ 'sel' => array(),
4629
+ 'selbu' => array(),
4630
+ 'selje' => array(),
4631
+ 'seljord' => array(),
4632
+ 'sigdal' => array(),
4633
+ 'siljan' => array(),
4634
+ 'sirdal' => array(),
4635
+ 'skaun' => array(),
4636
+ 'skedsmo' => array(),
4637
+ 'ski' => array(),
4638
+ 'skien' => array(),
4639
+ 'skiptvet' => array(),
4640
+ 'skjervoy' => array(),
4641
+ 'skjervøy' => array(),
4642
+ 'skierva' => array(),
4643
+ 'skiervá' => array(),
4644
+ 'skjak' => array(),
4645
+ 'skjåk' => array(),
4646
+ 'skodje' => array(),
4647
+ 'skanland' => array(),
4648
+ 'skånland' => array(),
4649
+ 'skanit' => array(),
4650
+ 'skánit' => array(),
4651
+ 'smola' => array(),
4652
+ 'smøla' => array(),
4653
+ 'snillfjord' => array(),
4654
+ 'snasa' => array(),
4655
+ 'snåsa' => array(),
4656
+ 'snoasa' => array(),
4657
+ 'snaase' => array(),
4658
+ 'snåase' => array(),
4659
+ 'sogndal' => array(),
4660
+ 'sokndal' => array(),
4661
+ 'sola' => array(),
4662
+ 'solund' => array(),
4663
+ 'songdalen' => array(),
4664
+ 'sortland' => array(),
4665
+ 'spydeberg' => array(),
4666
+ 'stange' => array(),
4667
+ 'stavanger' => array(),
4668
+ 'steigen' => array(),
4669
+ 'steinkjer' => array(),
4670
+ 'stjordal' => array(),
4671
+ 'stjørdal' => array(),
4672
+ 'stokke' => array(),
4673
+ 'stor-elvdal' => array(),
4674
+ 'stord' => array(),
4675
+ 'stordal' => array(),
4676
+ 'storfjord' => array(),
4677
+ 'omasvuotna' => array(),
4678
+ 'strand' => array(),
4679
+ 'stranda' => array(),
4680
+ 'stryn' => array(),
4681
+ 'sula' => array(),
4682
+ 'suldal' => array(),
4683
+ 'sund' => array(),
4684
+ 'sunndal' => array(),
4685
+ 'surnadal' => array(),
4686
+ 'sveio' => array(),
4687
+ 'svelvik' => array(),
4688
+ 'sykkylven' => array(),
4689
+ 'sogne' => array(),
4690
+ 'søgne' => array(),
4691
+ 'somna' => array(),
4692
+ 'sømna' => array(),
4693
+ 'sondre-land' => array(),
4694
+ 'søndre-land' => array(),
4695
+ 'sor-aurdal' => array(),
4696
+ 'sør-aurdal' => array(),
4697
+ 'sor-fron' => array(),
4698
+ 'sør-fron' => array(),
4699
+ 'sor-odal' => array(),
4700
+ 'sør-odal' => array(),
4701
+ 'sor-varanger' => array(),
4702
+ 'sør-varanger' => array(),
4703
+ 'matta-varjjat' => array(),
4704
+ 'mátta-várjjat' => array(),
4705
+ 'sorfold' => array(),
4706
+ 'sørfold' => array(),
4707
+ 'sorreisa' => array(),
4708
+ 'sørreisa' => array(),
4709
+ 'sorum' => array(),
4710
+ 'sørum' => array(),
4711
+ 'tana' => array(),
4712
+ 'deatnu' => array(),
4713
+ 'time' => array(),
4714
+ 'tingvoll' => array(),
4715
+ 'tinn' => array(),
4716
+ 'tjeldsund' => array(),
4717
+ 'dielddanuorri' => array(),
4718
+ 'tjome' => array(),
4719
+ 'tjøme' => array(),
4720
+ 'tokke' => array(),
4721
+ 'tolga' => array(),
4722
+ 'torsken' => array(),
4723
+ 'tranoy' => array(),
4724
+ 'tranøy' => array(),
4725
+ 'tromso' => array(),
4726
+ 'tromsø' => array(),
4727
+ 'tromsa' => array(),
4728
+ 'romsa' => array(),
4729
+ 'trondheim' => array(),
4730
+ 'troandin' => array(),
4731
+ 'trysil' => array(),
4732
+ 'trana' => array(),
4733
+ 'træna' => array(),
4734
+ 'trogstad' => array(),
4735
+ 'trøgstad' => array(),
4736
+ 'tvedestrand' => array(),
4737
+ 'tydal' => array(),
4738
+ 'tynset' => array(),
4739
+ 'tysfjord' => array(),
4740
+ 'divtasvuodna' => array(),
4741
+ 'divttasvuotna' => array(),
4742
+ 'tysnes' => array(),
4743
+ 'tysvar' => array(),
4744
+ 'tysvær' => array(),
4745
+ 'tonsberg' => array(),
4746
+ 'tønsberg' => array(),
4747
+ 'ullensaker' => array(),
4748
+ 'ullensvang' => array(),
4749
+ 'ulvik' => array(),
4750
+ 'utsira' => array(),
4751
+ 'vadso' => array(),
4752
+ 'vadsø' => array(),
4753
+ 'cahcesuolo' => array(),
4754
+ 'čáhcesuolo' => array(),
4755
+ 'vaksdal' => array(),
4756
+ 'valle' => array(),
4757
+ 'vang' => array(),
4758
+ 'vanylven' => array(),
4759
+ 'vardo' => array(),
4760
+ 'vardø' => array(),
4761
+ 'varggat' => array(),
4762
+ 'várggát' => array(),
4763
+ 'vefsn' => array(),
4764
+ 'vaapste' => array(),
4765
+ 'vega' => array(),
4766
+ 'vegarshei' => array(),
4767
+ 'vegårshei' => array(),
4768
+ 'vennesla' => array(),
4769
+ 'verdal' => array(),
4770
+ 'verran' => array(),
4771
+ 'vestby' => array(),
4772
+ 'vestnes' => array(),
4773
+ 'vestre-slidre' => array(),
4774
+ 'vestre-toten' => array(),
4775
+ 'vestvagoy' => array(),
4776
+ 'vestvågøy' => array(),
4777
+ 'vevelstad' => array(),
4778
+ 'vik' => array(),
4779
+ 'vikna' => array(),
4780
+ 'vindafjord' => array(),
4781
+ 'volda' => array(),
4782
+ 'voss' => array(),
4783
+ 'varoy' => array(),
4784
+ 'værøy' => array(),
4785
+ 'vagan' => array(),
4786
+ 'vågan' => array(),
4787
+ 'voagat' => array(),
4788
+ 'vagsoy' => array(),
4789
+ 'vågsøy' => array(),
4790
+ 'vaga' => array(),
4791
+ 'vågå' => array(),
4792
+ 'ostfold' => array('valer' => array()),
4793
+ 'østfold' => array('våler' => array()),
4794
+ 'co' => array(),
4795
+ 'blogspot' => array()),
4796
+ 'np' => array('*' => array()),
4797
+ 'nr' => array('biz' => array(),
4798
+ 'info' => array(),
4799
+ 'gov' => array(),
4800
+ 'edu' => array(),
4801
+ 'org' => array(),
4802
+ 'net' => array(),
4803
+ 'com' => array()),
4804
+ 'nu' => array('merseine' => array(),
4805
+ 'mine' => array(),
4806
+ 'shacknet' => array()),
4807
+ 'nz' => array('ac' => array(),
4808
+ 'co' => array('blogspot' => array()),
4809
+ 'cri' => array(),
4810
+ 'geek' => array(),
4811
+ 'gen' => array(),
4812
+ 'govt' => array(),
4813
+ 'health' => array(),
4814
+ 'iwi' => array(),
4815
+ 'kiwi' => array(),
4816
+ 'maori' => array(),
4817
+ 'mil' => array(),
4818
+ 'māori' => array(),
4819
+ 'net' => array(),
4820
+ 'org' => array(),
4821
+ 'parliament' => array(),
4822
+ 'school' => array()),
4823
+ 'om' => array('co' => array(),
4824
+ 'com' => array(),
4825
+ 'edu' => array(),
4826
+ 'gov' => array(),
4827
+ 'med' => array(),
4828
+ 'museum' => array(),
4829
+ 'net' => array(),
4830
+ 'org' => array(),
4831
+ 'pro' => array()),
4832
+ 'org' => array('ae' => array(),
4833
+ 'us' => array(),
4834
+ 'dyndns' => array('go' => array(),
4835
+ 'home' => array()),
4836
+ 'blogdns' => array(),
4837
+ 'blogsite' => array(),
4838
+ 'boldlygoingnowhere' => array(),
4839
+ 'dnsalias' => array(),
4840
+ 'dnsdojo' => array(),
4841
+ 'doesntexist' => array(),
4842
+ 'dontexist' => array(),
4843
+ 'doomdns' => array(),
4844
+ 'dvrdns' => array(),
4845
+ 'dynalias' => array(),
4846
+ 'endofinternet' => array(),
4847
+ 'endoftheinternet' => array(),
4848
+ 'from-me' => array(),
4849
+ 'game-host' => array(),
4850
+ 'gotdns' => array(),
4851
+ 'hobby-site' => array(),
4852
+ 'homedns' => array(),
4853
+ 'homeftp' => array(),
4854
+ 'homelinux' => array(),
4855
+ 'homeunix' => array(),
4856
+ 'is-a-bruinsfan' => array(),
4857
+ 'is-a-candidate' => array(),
4858
+ 'is-a-celticsfan' => array(),
4859
+ 'is-a-chef' => array(),
4860
+ 'is-a-geek' => array(),
4861
+ 'is-a-knight' => array(),
4862
+ 'is-a-linux-user' => array(),
4863
+ 'is-a-patsfan' => array(),
4864
+ 'is-a-soxfan' => array(),
4865
+ 'is-found' => array(),
4866
+ 'is-lost' => array(),
4867
+ 'is-saved' => array(),
4868
+ 'is-very-bad' => array(),
4869
+ 'is-very-evil' => array(),
4870
+ 'is-very-good' => array(),
4871
+ 'is-very-nice' => array(),
4872
+ 'is-very-sweet' => array(),
4873
+ 'isa-geek' => array(),
4874
+ 'kicks-ass' => array(),
4875
+ 'misconfused' => array(),
4876
+ 'podzone' => array(),
4877
+ 'readmyblog' => array(),
4878
+ 'selfip' => array(),
4879
+ 'sellsyourhome' => array(),
4880
+ 'servebbs' => array(),
4881
+ 'serveftp' => array(),
4882
+ 'servegame' => array(),
4883
+ 'stuff-4-sale' => array(),
4884
+ 'webhop' => array(),
4885
+ 'za' => array()),
4886
+ 'pa' => array('ac' => array(),
4887
+ 'gob' => array(),
4888
+ 'com' => array(),
4889
+ 'org' => array(),
4890
+ 'sld' => array(),
4891
+ 'edu' => array(),
4892
+ 'net' => array(),
4893
+ 'ing' => array(),
4894
+ 'abo' => array(),
4895
+ 'med' => array(),
4896
+ 'nom' => array()),
4897
+ 'pe' => array('edu' => array(),
4898
+ 'gob' => array(),
4899
+ 'nom' => array(),
4900
+ 'mil' => array(),
4901
+ 'org' => array(),
4902
+ 'com' => array(),
4903
+ 'net' => array()),
4904
+ 'pf' => array('com' => array(),
4905
+ 'org' => array(),
4906
+ 'edu' => array()),
4907
+ 'pg' => array('*' => array()),
4908
+ 'ph' => array('com' => array(),
4909
+ 'net' => array(),
4910
+ 'org' => array(),
4911
+ 'gov' => array(),
4912
+ 'edu' => array(),
4913
+ 'ngo' => array(),
4914
+ 'mil' => array(),
4915
+ 'i' => array()),
4916
+ 'pk' => array('com' => array(),
4917
+ 'net' => array(),
4918
+ 'edu' => array(),
4919
+ 'org' => array(),
4920
+ 'fam' => array(),
4921
+ 'biz' => array(),
4922
+ 'web' => array(),
4923
+ 'gov' => array(),
4924
+ 'gob' => array(),
4925
+ 'gok' => array(),
4926
+ 'gon' => array(),
4927
+ 'gop' => array(),
4928
+ 'gos' => array(),
4929
+ 'info' => array()),
4930
+ 'pl' => array('aid' => array(),
4931
+ 'agro' => array(),
4932
+ 'atm' => array(),
4933
+ 'auto' => array(),
4934
+ 'biz' => array(),
4935
+ 'com' => array(),
4936
+ 'edu' => array(),
4937
+ 'gmina' => array(),
4938
+ 'gsm' => array(),
4939
+ 'info' => array(),
4940
+ 'mail' => array(),
4941
+ 'miasta' => array(),
4942
+ 'media' => array(),
4943
+ 'mil' => array(),
4944
+ 'net' => array(),
4945
+ 'nieruchomosci' => array(),
4946
+ 'nom' => array(),
4947
+ 'org' => array(),
4948
+ 'pc' => array(),
4949
+ 'powiat' => array(),
4950
+ 'priv' => array(),
4951
+ 'realestate' => array(),
4952
+ 'rel' => array(),
4953
+ 'sex' => array(),
4954
+ 'shop' => array(),
4955
+ 'sklep' => array(),
4956
+ 'sos' => array(),
4957
+ 'szkola' => array(),
4958
+ 'targi' => array(),
4959
+ 'tm' => array(),
4960
+ 'tourism' => array(),
4961
+ 'travel' => array(),
4962
+ 'turystyka' => array(),
4963
+ '6bone' => array(),
4964
+ 'art' => array(),
4965
+ 'mbone' => array(),
4966
+ 'gov' => array('uw' => array(),
4967
+ 'um' => array(),
4968
+ 'ug' => array(),
4969
+ 'upow' => array(),
4970
+ 'starostwo' => array(),
4971
+ 'so' => array(),
4972
+ 'sr' => array(),
4973
+ 'po' => array(),
4974
+ 'pa' => array()),
4975
+ 'ngo' => array(),
4976
+ 'irc' => array(),
4977
+ 'usenet' => array(),
4978
+ 'augustow' => array(),
4979
+ 'babia-gora' => array(),
4980
+ 'bedzin' => array(),
4981
+ 'beskidy' => array(),
4982
+ 'bialowieza' => array(),
4983
+ 'bialystok' => array(),
4984
+ 'bielawa' => array(),
4985
+ 'bieszczady' => array(),
4986
+ 'boleslawiec' => array(),
4987
+ 'bydgoszcz' => array(),
4988
+ 'bytom' => array(),
4989
+ 'cieszyn' => array(),
4990
+ 'czeladz' => array(),
4991
+ 'czest' => array(),
4992
+ 'dlugoleka' => array(),
4993
+ 'elblag' => array(),
4994
+ 'elk' => array(),
4995
+ 'glogow' => array(),
4996
+ 'gniezno' => array(),
4997
+ 'gorlice' => array(),
4998
+ 'grajewo' => array(),
4999
+ 'ilawa' => array(),
5000
+ 'jaworzno' => array(),
5001
+ 'jelenia-gora' => array(),
5002
+ 'jgora' => array(),
5003
+ 'kalisz' => array(),
5004
+ 'kazimierz-dolny' => array(),
5005
+ 'karpacz' => array(),
5006
+ 'kartuzy' => array(),
5007
+ 'kaszuby' => array(),
5008
+ 'katowice' => array(),
5009
+ 'kepno' => array(),
5010
+ 'ketrzyn' => array(),
5011
+ 'klodzko' => array(),
5012
+ 'kobierzyce' => array(),
5013
+ 'kolobrzeg' => array(),
5014
+ 'konin' => array(),
5015
+ 'konskowola' => array(),
5016
+ 'kutno' => array(),
5017
+ 'lapy' => array(),
5018
+ 'lebork' => array(),
5019
+ 'legnica' => array(),
5020
+ 'lezajsk' => array(),
5021
+ 'limanowa' => array(),
5022
+ 'lomza' => array(),
5023
+ 'lowicz' => array(),
5024
+ 'lubin' => array(),
5025
+ 'lukow' => array(),
5026
+ 'malbork' => array(),
5027
+ 'malopolska' => array(),
5028
+ 'mazowsze' => array(),
5029
+ 'mazury' => array(),
5030
+ 'mielec' => array(),
5031
+ 'mielno' => array(),
5032
+ 'mragowo' => array(),
5033
+ 'naklo' => array(),
5034
+ 'nowaruda' => array(),
5035
+ 'nysa' => array(),
5036
+ 'olawa' => array(),
5037
+ 'olecko' => array(),
5038
+ 'olkusz' => array(),
5039
+ 'olsztyn' => array(),
5040
+ 'opoczno' => array(),
5041
+ 'opole' => array(),
5042
+ 'ostroda' => array(),
5043
+ 'ostroleka' => array(),
5044
+ 'ostrowiec' => array(),
5045
+ 'ostrowwlkp' => array(),
5046
+ 'pila' => array(),
5047
+ 'pisz' => array(),
5048
+ 'podhale' => array(),
5049
+ 'podlasie' => array(),
5050
+ 'polkowice' => array(),
5051
+ 'pomorze' => array(),
5052
+ 'pomorskie' => array(),
5053
+ 'prochowice' => array(),
5054
+ 'pruszkow' => array(),
5055
+ 'przeworsk' => array(),
5056
+ 'pulawy' => array(),
5057
+ 'radom' => array(),
5058
+ 'rawa-maz' => array(),
5059
+ 'rybnik' => array(),
5060
+ 'rzeszow' => array(),
5061
+ 'sanok' => array(),
5062
+ 'sejny' => array(),
5063
+ 'siedlce' => array(),
5064
+ 'slask' => array(),
5065
+ 'slupsk' => array(),
5066
+ 'sosnowiec' => array(),
5067
+ 'stalowa-wola' => array(),
5068
+ 'skoczow' => array(),
5069
+ 'starachowice' => array(),
5070
+ 'stargard' => array(),
5071
+ 'suwalki' => array(),
5072
+ 'swidnica' => array(),
5073
+ 'swiebodzin' => array(),
5074
+ 'swinoujscie' => array(),
5075
+ 'szczecin' => array(),
5076
+ 'szczytno' => array(),
5077
+ 'tarnobrzeg' => array(),
5078
+ 'tgory' => array(),
5079
+ 'turek' => array(),
5080
+ 'tychy' => array(),
5081
+ 'ustka' => array(),
5082
+ 'walbrzych' => array(),
5083
+ 'warmia' => array(),
5084
+ 'warszawa' => array(),
5085
+ 'waw' => array(),
5086
+ 'wegrow' => array(),
5087
+ 'wielun' => array(),
5088
+ 'wlocl' => array(),
5089
+ 'wloclawek' => array(),
5090
+ 'wodzislaw' => array(),
5091
+ 'wolomin' => array(),
5092
+ 'wroclaw' => array(),
5093
+ 'zachpomor' => array(),
5094
+ 'zagan' => array(),
5095
+ 'zarow' => array(),
5096
+ 'zgora' => array(),
5097
+ 'zgorzelec' => array(),
5098
+ 'gda' => array(),
5099
+ 'gdansk' => array(),
5100
+ 'gdynia' => array(),
5101
+ 'med' => array(),
5102
+ 'sopot' => array(),
5103
+ 'gliwice' => array(),
5104
+ 'krakow' => array(),
5105
+ 'poznan' => array(),
5106
+ 'wroc' => array(),
5107
+ 'zakopane' => array(),
5108
+ 'co' => array()),
5109
+ 'pm' => array(),
5110
+ 'pn' => array('gov' => array(),
5111
+ 'co' => array(),
5112
+ 'org' => array(),
5113
+ 'edu' => array(),
5114
+ 'net' => array()),
5115
+ 'post' => array(),
5116
+ 'pr' => array('com' => array(),
5117
+ 'net' => array(),
5118
+ 'org' => array(),
5119
+ 'gov' => array(),
5120
+ 'edu' => array(),
5121
+ 'isla' => array(),
5122
+ 'pro' => array(),
5123
+ 'biz' => array(),
5124
+ 'info' => array(),
5125
+ 'name' => array(),
5126
+ 'est' => array(),
5127
+ 'prof' => array(),
5128
+ 'ac' => array()),
5129
+ 'pro' => array('aca' => array(),
5130
+ 'bar' => array(),
5131
+ 'cpa' => array(),
5132
+ 'jur' => array(),
5133
+ 'law' => array(),
5134
+ 'med' => array(),
5135
+ 'eng' => array()),
5136
+ 'ps' => array('edu' => array(),
5137
+ 'gov' => array(),
5138
+ 'sec' => array(),
5139
+ 'plo' => array(),
5140
+ 'com' => array(),
5141
+ 'org' => array(),
5142
+ 'net' => array()),
5143
+ 'pt' => array('net' => array(),
5144
+ 'gov' => array(),
5145
+ 'org' => array(),
5146
+ 'edu' => array(),
5147
+ 'int' => array(),
5148
+ 'publ' => array(),
5149
+ 'com' => array(),
5150
+ 'nome' => array(),
5151
+ 'blogspot' => array()),
5152
+ 'pw' => array('co' => array(),
5153
+ 'ne' => array(),
5154
+ 'or' => array(),
5155
+ 'ed' => array(),
5156
+ 'go' => array(),
5157
+ 'belau' => array()),
5158
+ 'py' => array('com' => array(),
5159
+ 'coop' => array(),
5160
+ 'edu' => array(),
5161
+ 'gov' => array(),
5162
+ 'mil' => array(),
5163
+ 'net' => array(),
5164
+ 'org' => array()),
5165
+ 'qa' => array('com' => array(),
5166
+ 'edu' => array(),
5167
+ 'gov' => array(),
5168
+ 'mil' => array(),
5169
+ 'name' => array(),
5170
+ 'net' => array(),
5171
+ 'org' => array(),
5172
+ 'sch' => array()),
5173
+ 're' => array('com' => array(),
5174
+ 'asso' => array(),
5175
+ 'nom' => array(),
5176
+ 'blogspot' => array()),
5177
+ 'ro' => array('com' => array(),
5178
+ 'org' => array(),
5179
+ 'tm' => array(),
5180
+ 'nt' => array(),
5181
+ 'nom' => array(),
5182
+ 'info' => array(),
5183
+ 'rec' => array(),
5184
+ 'arts' => array(),
5185
+ 'firm' => array(),
5186
+ 'store' => array(),
5187
+ 'www' => array(),
5188
+ 'blogspot' => array()),
5189
+ 'rs' => array('co' => array(),
5190
+ 'org' => array(),
5191
+ 'edu' => array(),
5192
+ 'ac' => array(),
5193
+ 'gov' => array(),
5194
+ 'in' => array()),
5195
+ 'ru' => array('ac' => array(),
5196
+ 'com' => array(),
5197
+ 'edu' => array(),
5198
+ 'int' => array(),
5199
+ 'net' => array(),
5200
+ 'org' => array(),
5201
+ 'pp' => array(),
5202
+ 'adygeya' => array(),
5203
+ 'altai' => array(),
5204
+ 'amur' => array(),
5205
+ 'arkhangelsk' => array(),
5206
+ 'astrakhan' => array(),
5207
+ 'bashkiria' => array(),
5208
+ 'belgorod' => array(),
5209
+ 'bir' => array(),
5210
+ 'bryansk' => array(),
5211
+ 'buryatia' => array(),
5212
+ 'cbg' => array(),
5213
+ 'chel' => array(),
5214
+ 'chelyabinsk' => array(),
5215
+ 'chita' => array(),
5216
+ 'chukotka' => array(),
5217
+ 'chuvashia' => array(),
5218
+ 'dagestan' => array(),
5219
+ 'dudinka' => array(),
5220
+ 'e-burg' => array(),
5221
+ 'grozny' => array(),
5222
+ 'irkutsk' => array(),
5223
+ 'ivanovo' => array(),
5224
+ 'izhevsk' => array(),
5225
+ 'jar' => array(),
5226
+ 'joshkar-ola' => array(),
5227
+ 'kalmykia' => array(),
5228
+ 'kaluga' => array(),
5229
+ 'kamchatka' => array(),
5230
+ 'karelia' => array(),
5231
+ 'kazan' => array(),
5232
+ 'kchr' => array(),
5233
+ 'kemerovo' => array(),
5234
+ 'khabarovsk' => array(),
5235
+ 'khakassia' => array(),
5236
+ 'khv' => array(),
5237
+ 'kirov' => array(),
5238
+ 'koenig' => array(),
5239
+ 'komi' => array(),
5240
+ 'kostroma' => array(),
5241
+ 'krasnoyarsk' => array(),
5242
+ 'kuban' => array(),
5243
+ 'kurgan' => array(),
5244
+ 'kursk' => array(),
5245
+ 'lipetsk' => array(),
5246
+ 'magadan' => array(),
5247
+ 'mari' => array(),
5248
+ 'mari-el' => array(),
5249
+ 'marine' => array(),
5250
+ 'mordovia' => array(),
5251
+ 'mosreg' => array(),
5252
+ 'msk' => array(),
5253
+ 'murmansk' => array(),
5254
+ 'nalchik' => array(),
5255
+ 'nnov' => array(),
5256
+ 'nov' => array(),
5257
+ 'novosibirsk' => array(),
5258
+ 'nsk' => array(),
5259
+ 'omsk' => array(),
5260
+ 'orenburg' => array(),
5261
+ 'oryol' => array(),
5262
+ 'palana' => array(),
5263
+ 'penza' => array(),
5264
+ 'perm' => array(),
5265
+ 'ptz' => array(),
5266
+ 'rnd' => array(),
5267
+ 'ryazan' => array(),
5268
+ 'sakhalin' => array(),
5269
+ 'samara' => array(),
5270
+ 'saratov' => array(),
5271
+ 'simbirsk' => array(),
5272
+ 'smolensk' => array(),
5273
+ 'spb' => array(),
5274
+ 'stavropol' => array(),
5275
+ 'stv' => array(),
5276
+ 'surgut' => array(),
5277
+ 'tambov' => array(),
5278
+ 'tatarstan' => array(),
5279
+ 'tom' => array(),
5280
+ 'tomsk' => array(),
5281
+ 'tsaritsyn' => array(),
5282
+ 'tsk' => array(),
5283
+ 'tula' => array(),
5284
+ 'tuva' => array(),
5285
+ 'tver' => array(),
5286
+ 'tyumen' => array(),
5287
+ 'udm' => array(),
5288
+ 'udmurtia' => array(),
5289
+ 'ulan-ude' => array(),
5290
+ 'vladikavkaz' => array(),
5291
+ 'vladimir' => array(),
5292
+ 'vladivostok' => array(),
5293
+ 'volgograd' => array(),
5294
+ 'vologda' => array(),
5295
+ 'voronezh' => array(),
5296
+ 'vrn' => array(),
5297
+ 'vyatka' => array(),
5298
+ 'yakutia' => array(),
5299
+ 'yamal' => array(),
5300
+ 'yaroslavl' => array(),
5301
+ 'yekaterinburg' => array(),
5302
+ 'yuzhno-sakhalinsk' => array(),
5303
+ 'amursk' => array(),
5304
+ 'baikal' => array(),
5305
+ 'cmw' => array(),
5306
+ 'fareast' => array(),
5307
+ 'jamal' => array(),
5308
+ 'kms' => array(),
5309
+ 'k-uralsk' => array(),
5310
+ 'kustanai' => array(),
5311
+ 'kuzbass' => array(),
5312
+ 'magnitka' => array(),
5313
+ 'mytis' => array(),
5314
+ 'nakhodka' => array(),
5315
+ 'nkz' => array(),
5316
+ 'norilsk' => array(),
5317
+ 'oskol' => array(),
5318
+ 'pyatigorsk' => array(),
5319
+ 'rubtsovsk' => array(),
5320
+ 'snz' => array(),
5321
+ 'syzran' => array(),
5322
+ 'vdonsk' => array(),
5323
+ 'zgrad' => array(),
5324
+ 'gov' => array(),
5325
+ 'mil' => array(),
5326
+ 'test' => array()),
5327
+ 'rw' => array('gov' => array(),
5328
+ 'net' => array(),
5329
+ 'edu' => array(),
5330
+ 'ac' => array(),
5331
+ 'com' => array(),
5332
+ 'co' => array(),
5333
+ 'int' => array(),
5334
+ 'mil' => array(),
5335
+ 'gouv' => array()),
5336
+ 'sa' => array('com' => array(),
5337
+ 'net' => array(),
5338
+ 'org' => array(),
5339
+ 'gov' => array(),
5340
+ 'med' => array(),
5341
+ 'pub' => array(),
5342
+ 'edu' => array(),
5343
+ 'sch' => array()),
5344
+ 'sb' => array('com' => array(),
5345
+ 'edu' => array(),
5346
+ 'gov' => array(),
5347
+ 'net' => array(),
5348
+ 'org' => array()),
5349
+ 'sc' => array('com' => array(),
5350
+ 'gov' => array(),
5351
+ 'net' => array(),
5352
+ 'org' => array(),
5353
+ 'edu' => array()),
5354
+ 'sd' => array('com' => array(),
5355
+ 'net' => array(),
5356
+ 'org' => array(),
5357
+ 'edu' => array(),
5358
+ 'med' => array(),
5359
+ 'tv' => array(),
5360
+ 'gov' => array(),
5361
+ 'info' => array()),
5362
+ 'se' => array('a' => array(),
5363
+ 'ac' => array(),
5364
+ 'b' => array(),
5365
+ 'bd' => array(),
5366
+ 'brand' => array(),
5367
+ 'c' => array(),
5368
+ 'd' => array(),
5369
+ 'e' => array(),
5370
+ 'f' => array(),
5371
+ 'fh' => array(),
5372
+ 'fhsk' => array(),
5373
+ 'fhv' => array(),
5374
+ 'g' => array(),
5375
+ 'h' => array(),
5376
+ 'i' => array(),
5377
+ 'k' => array(),
5378
+ 'komforb' => array(),
5379
+ 'kommunalforbund' => array(),
5380
+ 'komvux' => array(),
5381
+ 'l' => array(),
5382
+ 'lanbib' => array(),
5383
+ 'm' => array(),
5384
+ 'n' => array(),
5385
+ 'naturbruksgymn' => array(),
5386
+ 'o' => array(),
5387
+ 'org' => array(),
5388
+ 'p' => array(),
5389
+ 'parti' => array(),
5390
+ 'pp' => array(),
5391
+ 'press' => array(),
5392
+ 'r' => array(),
5393
+ 's' => array(),
5394
+ 't' => array(),
5395
+ 'tm' => array(),
5396
+ 'u' => array(),
5397
+ 'w' => array(),
5398
+ 'x' => array(),
5399
+ 'y' => array(),
5400
+ 'z' => array(),
5401
+ 'com' => array(),
5402
+ 'blogspot' => array()),
5403
+ 'sg' => array('com' => array(),
5404
+ 'net' => array(),
5405
+ 'org' => array(),
5406
+ 'gov' => array(),
5407
+ 'edu' => array(),
5408
+ 'per' => array(),
5409
+ 'blogspot' => array()),
5410
+ 'sh' => array('com' => array(),
5411
+ 'net' => array(),
5412
+ 'gov' => array(),
5413
+ 'org' => array(),
5414
+ 'mil' => array()),
5415
+ 'si' => array(),
5416
+ 'sj' => array(),
5417
+ 'sk' => array('blogspot' => array()),
5418
+ 'sl' => array('com' => array(),
5419
+ 'net' => array(),
5420
+ 'edu' => array(),
5421
+ 'gov' => array(),
5422
+ 'org' => array()),
5423
+ 'sm' => array(),
5424
+ 'sn' => array('art' => array(),
5425
+ 'com' => array(),
5426
+ 'edu' => array(),
5427
+ 'gouv' => array(),
5428
+ 'org' => array(),
5429
+ 'perso' => array(),
5430
+ 'univ' => array()),
5431
+ 'so' => array('com' => array(),
5432
+ 'net' => array(),
5433
+ 'org' => array()),
5434
+ 'sr' => array(),
5435
+ 'st' => array('co' => array(),
5436
+ 'com' => array(),
5437
+ 'consulado' => array(),
5438
+ 'edu' => array(),
5439
+ 'embaixada' => array(),
5440
+ 'gov' => array(),
5441
+ 'mil' => array(),
5442
+ 'net' => array(),
5443
+ 'org' => array(),
5444
+ 'principe' => array(),
5445
+ 'saotome' => array(),
5446
+ 'store' => array()),
5447
+ 'su' => array(),
5448
+ 'sv' => array('com' => array(),
5449
+ 'edu' => array(),
5450
+ 'gob' => array(),
5451
+ 'org' => array(),
5452
+ 'red' => array()),
5453
+ 'sx' => array('gov' => array()),
5454
+ 'sy' => array('edu' => array(),
5455
+ 'gov' => array(),
5456
+ 'net' => array(),
5457
+ 'mil' => array(),
5458
+ 'com' => array(),
5459
+ 'org' => array()),
5460
+ 'sz' => array('co' => array(),
5461
+ 'ac' => array(),
5462
+ 'org' => array()),
5463
+ 'tc' => array(),
5464
+ 'td' => array('blogspot' => array()),
5465
+ 'tel' => array(),
5466
+ 'tf' => array(),
5467
+ 'tg' => array(),
5468
+ 'th' => array('ac' => array(),
5469
+ 'co' => array(),
5470
+ 'go' => array(),
5471
+ 'in' => array(),
5472
+ 'mi' => array(),
5473
+ 'net' => array(),
5474
+ 'or' => array()),
5475
+ 'tj' => array('ac' => array(),
5476
+ 'biz' => array(),
5477
+ 'co' => array(),
5478
+ 'com' => array(),
5479
+ 'edu' => array(),
5480
+ 'go' => array(),
5481
+ 'gov' => array(),
5482
+ 'int' => array(),
5483
+ 'mil' => array(),
5484
+ 'name' => array(),
5485
+ 'net' => array(),
5486
+ 'nic' => array(),
5487
+ 'org' => array(),
5488
+ 'test' => array(),
5489
+ 'web' => array()),
5490
+ 'tk' => array(),
5491
+ 'tl' => array('gov' => array()),
5492
+ 'tm' => array('com' => array(),
5493
+ 'co' => array(),
5494
+ 'org' => array(),
5495
+ 'net' => array(),
5496
+ 'nom' => array(),
5497
+ 'gov' => array(),
5498
+ 'mil' => array(),
5499
+ 'edu' => array()),
5500
+ 'tn' => array('com' => array(),
5501
+ 'ens' => array(),
5502
+ 'fin' => array(),
5503
+ 'gov' => array(),
5504
+ 'ind' => array(),
5505
+ 'intl' => array(),
5506
+ 'nat' => array(),
5507
+ 'net' => array(),
5508
+ 'org' => array(),
5509
+ 'info' => array(),
5510
+ 'perso' => array(),
5511
+ 'tourism' => array(),
5512
+ 'edunet' => array(),
5513
+ 'rnrt' => array(),
5514
+ 'rns' => array(),
5515
+ 'rnu' => array(),
5516
+ 'mincom' => array(),
5517
+ 'agrinet' => array(),
5518
+ 'defense' => array(),
5519
+ 'turen' => array()),
5520
+ 'to' => array('com' => array(),
5521
+ 'gov' => array(),
5522
+ 'net' => array(),
5523
+ 'org' => array(),
5524
+ 'edu' => array(),
5525
+ 'mil' => array()),
5526
+ 'tp' => array(),
5527
+ 'tr' => array('com' => array(),
5528
+ 'info' => array(),
5529
+ 'biz' => array(),
5530
+ 'net' => array(),
5531
+ 'org' => array(),
5532
+ 'web' => array(),
5533
+ 'gen' => array(),
5534
+ 'tv' => array(),
5535
+ 'av' => array(),
5536
+ 'dr' => array(),
5537
+ 'bbs' => array(),
5538
+ 'name' => array(),
5539
+ 'tel' => array(),
5540
+ 'gov' => array(),
5541
+ 'bel' => array(),
5542
+ 'pol' => array(),
5543
+ 'mil' => array(),
5544
+ 'k12' => array(),
5545
+ 'edu' => array(),
5546
+ 'kep' => array(),
5547
+ 'nc' => array('gov' => array())),
5548
+ 'travel' => array(),
5549
+ 'tt' => array('co' => array(),
5550
+ 'com' => array(),
5551
+ 'org' => array(),
5552
+ 'net' => array(),
5553
+ 'biz' => array(),
5554
+ 'info' => array(),
5555
+ 'pro' => array(),
5556
+ 'int' => array(),
5557
+ 'coop' => array(),
5558
+ 'jobs' => array(),
5559
+ 'mobi' => array(),
5560
+ 'travel' => array(),
5561
+ 'museum' => array(),
5562
+ 'aero' => array(),
5563
+ 'name' => array(),
5564
+ 'gov' => array(),
5565
+ 'edu' => array()),
5566
+ 'tv' => array('dyndns' => array(),
5567
+ 'better-than' => array(),
5568
+ 'on-the-web' => array(),
5569
+ 'worse-than' => array()),
5570
+ 'tw' => array('edu' => array(),
5571
+ 'gov' => array(),
5572
+ 'mil' => array(),
5573
+ 'com' => array(),
5574
+ 'net' => array(),
5575
+ 'org' => array(),
5576
+ 'idv' => array(),
5577
+ 'game' => array(),
5578
+ 'ebiz' => array(),
5579
+ 'club' => array(),
5580
+ '網路' => array(),
5581
+ '組織' => array(),
5582
+ '商業' => array(),
5583
+ 'blogspot' => array()),
5584
+ 'tz' => array('ac' => array(),
5585
+ 'co' => array(),
5586
+ 'go' => array(),
5587
+ 'hotel' => array(),
5588
+ 'info' => array(),
5589
+ 'me' => array(),
5590
+ 'mil' => array(),
5591
+ 'mobi' => array(),
5592
+ 'ne' => array(),
5593
+ 'or' => array(),
5594
+ 'sc' => array(),
5595
+ 'tv' => array()),
5596
+ 'ua' => array('com' => array(),
5597
+ 'edu' => array(),
5598
+ 'gov' => array(),
5599
+ 'in' => array(),
5600
+ 'net' => array(),
5601
+ 'org' => array(),
5602
+ 'cherkassy' => array(),
5603
+ 'cherkasy' => array(),
5604
+ 'chernigov' => array(),
5605
+ 'chernihiv' => array(),
5606
+ 'chernivtsi' => array(),
5607
+ 'chernovtsy' => array(),
5608
+ 'ck' => array(),
5609
+ 'cn' => array(),
5610
+ 'cr' => array(),
5611
+ 'crimea' => array(),
5612
+ 'cv' => array(),
5613
+ 'dn' => array(),
5614
+ 'dnepropetrovsk' => array(),
5615
+ 'dnipropetrovsk' => array(),
5616
+ 'dominic' => array(),
5617
+ 'donetsk' => array(),
5618
+ 'dp' => array(),
5619
+ 'if' => array(),
5620
+ 'ivano-frankivsk' => array(),
5621
+ 'kh' => array(),
5622
+ 'kharkiv' => array(),
5623
+ 'kharkov' => array(),
5624
+ 'kherson' => array(),
5625
+ 'khmelnitskiy' => array(),
5626
+ 'khmelnytskyi' => array(),
5627
+ 'kiev' => array(),
5628
+ 'kirovograd' => array(),
5629
+ 'km' => array(),
5630
+ 'kr' => array(),
5631
+ 'krym' => array(),
5632
+ 'ks' => array(),
5633
+ 'kv' => array(),
5634
+ 'kyiv' => array(),
5635
+ 'lg' => array(),
5636
+ 'lt' => array(),
5637
+ 'lugansk' => array(),
5638
+ 'lutsk' => array(),
5639
+ 'lv' => array(),
5640
+ 'lviv' => array(),
5641
+ 'mk' => array(),
5642
+ 'mykolaiv' => array(),
5643
+ 'nikolaev' => array(),
5644
+ 'od' => array(),
5645
+ 'odesa' => array(),
5646
+ 'odessa' => array(),
5647
+ 'pl' => array(),
5648
+ 'poltava' => array(),
5649
+ 'rivne' => array(),
5650
+ 'rovno' => array(),
5651
+ 'rv' => array(),
5652
+ 'sb' => array(),
5653
+ 'sebastopol' => array(),
5654
+ 'sevastopol' => array(),
5655
+ 'sm' => array(),
5656
+ 'sumy' => array(),
5657
+ 'te' => array(),
5658
+ 'ternopil' => array(),
5659
+ 'uz' => array(),
5660
+ 'uzhgorod' => array(),
5661
+ 'vinnica' => array(),
5662
+ 'vinnytsia' => array(),
5663
+ 'vn' => array(),
5664
+ 'volyn' => array(),
5665
+ 'yalta' => array(),
5666
+ 'zaporizhzhe' => array(),
5667
+ 'zaporizhzhia' => array(),
5668
+ 'zhitomir' => array(),
5669
+ 'zhytomyr' => array(),
5670
+ 'zp' => array(),
5671
+ 'zt' => array(),
5672
+ 'co' => array(),
5673
+ 'pp' => array()),
5674
+ 'ug' => array('co' => array(),
5675
+ 'or' => array(),
5676
+ 'ac' => array(),
5677
+ 'sc' => array(),
5678
+ 'go' => array(),
5679
+ 'ne' => array(),
5680
+ 'com' => array(),
5681
+ 'org' => array()),
5682
+ 'uk' => array('ac' => array(),
5683
+ 'co' => array('blogspot' => array()),
5684
+ 'gov' => array('service' => array()),
5685
+ 'ltd' => array(),
5686
+ 'me' => array(),
5687
+ 'net' => array(),
5688
+ 'nhs' => array(),
5689
+ 'org' => array(),
5690
+ 'plc' => array(),
5691
+ 'police' => array(),
5692
+ 'sch' => array('*' => array())),
5693
+ 'us' => array('dni' => array(),
5694
+ 'fed' => array(),
5695
+ 'isa' => array(),
5696
+ 'kids' => array(),
5697
+ 'nsn' => array(),
5698
+ 'ak' => array('k12' => array(),
5699
+ 'cc' => array(),
5700
+ 'lib' => array()),
5701
+ 'al' => array('k12' => array(),
5702
+ 'cc' => array(),
5703
+ 'lib' => array()),
5704
+ 'ar' => array('k12' => array(),
5705
+ 'cc' => array(),
5706
+ 'lib' => array()),
5707
+ 'as' => array('k12' => array(),
5708
+ 'cc' => array(),
5709
+ 'lib' => array()),
5710
+ 'az' => array('k12' => array(),
5711
+ 'cc' => array(),
5712
+ 'lib' => array()),
5713
+ 'ca' => array('k12' => array(),
5714
+ 'cc' => array(),
5715
+ 'lib' => array()),
5716
+ 'co' => array('k12' => array(),
5717
+ 'cc' => array(),
5718
+ 'lib' => array()),
5719
+ 'ct' => array('k12' => array(),
5720
+ 'cc' => array(),
5721
+ 'lib' => array()),
5722
+ 'dc' => array('k12' => array(),
5723
+ 'cc' => array(),
5724
+ 'lib' => array()),
5725
+ 'de' => array('k12' => array(),
5726
+ 'cc' => array(),
5727
+ 'lib' => array()),
5728
+ 'fl' => array('k12' => array(),
5729
+ 'cc' => array(),
5730
+ 'lib' => array()),
5731
+ 'ga' => array('k12' => array(),
5732
+ 'cc' => array(),
5733
+ 'lib' => array()),
5734
+ 'gu' => array('k12' => array(),
5735
+ 'cc' => array(),
5736
+ 'lib' => array()),
5737
+ 'hi' => array('cc' => array(),
5738
+ 'lib' => array()),
5739
+ 'ia' => array('k12' => array(),
5740
+ 'cc' => array(),
5741
+ 'lib' => array()),
5742
+ 'id' => array('k12' => array(),
5743
+ 'cc' => array(),
5744
+ 'lib' => array()),
5745
+ 'il' => array('k12' => array(),
5746
+ 'cc' => array(),
5747
+ 'lib' => array()),
5748
+ 'in' => array('k12' => array(),
5749
+ 'cc' => array(),
5750
+ 'lib' => array()),
5751
+ 'ks' => array('k12' => array(),
5752
+ 'cc' => array(),
5753
+ 'lib' => array()),
5754
+ 'ky' => array('k12' => array(),
5755
+ 'cc' => array(),
5756
+ 'lib' => array()),
5757
+ 'la' => array('k12' => array(),
5758
+ 'cc' => array(),
5759
+ 'lib' => array()),
5760
+ 'ma' => array('k12' => array('pvt' => array(),
5761
+ 'chtr' => array(),
5762
+ 'paroch' => array()),
5763
+ 'cc' => array(),
5764
+ 'lib' => array()),
5765
+ 'md' => array('k12' => array(),
5766
+ 'cc' => array(),
5767
+ 'lib' => array()),
5768
+ 'me' => array('k12' => array(),
5769
+ 'cc' => array(),
5770
+ 'lib' => array()),
5771
+ 'mi' => array('k12' => array(),
5772
+ 'cc' => array(),
5773
+ 'lib' => array()),
5774
+ 'mn' => array('k12' => array(),
5775
+ 'cc' => array(),
5776
+ 'lib' => array()),
5777
+ 'mo' => array('k12' => array(),
5778
+ 'cc' => array(),
5779
+ 'lib' => array()),
5780
+ 'ms' => array('k12' => array(),
5781
+ 'cc' => array(),
5782
+ 'lib' => array()),
5783
+ 'mt' => array('k12' => array(),
5784
+ 'cc' => array(),
5785
+ 'lib' => array()),
5786
+ 'nc' => array('k12' => array(),
5787
+ 'cc' => array(),
5788
+ 'lib' => array()),
5789
+ 'nd' => array('cc' => array(),
5790
+ 'lib' => array()),
5791
+ 'ne' => array('k12' => array(),
5792
+ 'cc' => array(),
5793
+ 'lib' => array()),
5794
+ 'nh' => array('k12' => array(),
5795
+ 'cc' => array(),
5796
+ 'lib' => array()),
5797
+ 'nj' => array('k12' => array(),
5798
+ 'cc' => array(),
5799
+ 'lib' => array()),
5800
+ 'nm' => array('k12' => array(),
5801
+ 'cc' => array(),
5802
+ 'lib' => array()),
5803
+ 'nv' => array('k12' => array(),
5804
+ 'cc' => array(),
5805
+ 'lib' => array()),
5806
+ 'ny' => array('k12' => array(),
5807
+ 'cc' => array(),
5808
+ 'lib' => array()),
5809
+ 'oh' => array('k12' => array(),
5810
+ 'cc' => array(),
5811
+ 'lib' => array()),
5812
+ 'ok' => array('k12' => array(),
5813
+ 'cc' => array(),
5814
+ 'lib' => array()),
5815
+ 'or' => array('k12' => array(),
5816
+ 'cc' => array(),
5817
+ 'lib' => array()),
5818
+ 'pa' => array('k12' => array(),
5819
+ 'cc' => array(),
5820
+ 'lib' => array()),
5821
+ 'pr' => array('k12' => array(),
5822
+ 'cc' => array(),
5823
+ 'lib' => array()),
5824
+ 'ri' => array('k12' => array(),
5825
+ 'cc' => array(),
5826
+ 'lib' => array()),
5827
+ 'sc' => array('k12' => array(),
5828
+ 'cc' => array(),
5829
+ 'lib' => array()),
5830
+ 'sd' => array('cc' => array(),
5831
+ 'lib' => array()),
5832
+ 'tn' => array('k12' => array(),
5833
+ 'cc' => array(),
5834
+ 'lib' => array()),
5835
+ 'tx' => array('k12' => array(),
5836
+ 'cc' => array(),
5837
+ 'lib' => array()),
5838
+ 'ut' => array('k12' => array(),
5839
+ 'cc' => array(),
5840
+ 'lib' => array()),
5841
+ 'vi' => array('k12' => array(),
5842
+ 'cc' => array(),
5843
+ 'lib' => array()),
5844
+ 'vt' => array('k12' => array(),
5845
+ 'cc' => array(),
5846
+ 'lib' => array()),
5847
+ 'va' => array('k12' => array(),
5848
+ 'cc' => array(),
5849
+ 'lib' => array()),
5850
+ 'wa' => array('k12' => array(),
5851
+ 'cc' => array(),
5852
+ 'lib' => array()),
5853
+ 'wi' => array('k12' => array(),
5854
+ 'cc' => array(),
5855
+ 'lib' => array()),
5856
+ 'wv' => array('cc' => array()),
5857
+ 'wy' => array('k12' => array(),
5858
+ 'cc' => array(),
5859
+ 'lib' => array()),
5860
+ 'is-by' => array(),
5861
+ 'land-4-sale' => array(),
5862
+ 'stuff-4-sale' => array()),
5863
+ 'uy' => array('com' => array(),
5864
+ 'edu' => array(),
5865
+ 'gub' => array(),
5866
+ 'mil' => array(),
5867
+ 'net' => array(),
5868
+ 'org' => array()),
5869
+ 'uz' => array('co' => array(),
5870
+ 'com' => array(),
5871
+ 'net' => array(),
5872
+ 'org' => array()),
5873
+ 'va' => array(),
5874
+ 'vc' => array('com' => array(),
5875
+ 'net' => array(),
5876
+ 'org' => array(),
5877
+ 'gov' => array(),
5878
+ 'mil' => array(),
5879
+ 'edu' => array()),
5880
+ 've' => array('arts' => array(),
5881
+ 'co' => array(),
5882
+ 'com' => array(),
5883
+ 'e12' => array(),
5884
+ 'edu' => array(),
5885
+ 'firm' => array(),
5886
+ 'gob' => array(),
5887
+ 'gov' => array(),
5888
+ 'info' => array(),
5889
+ 'int' => array(),
5890
+ 'mil' => array(),
5891
+ 'net' => array(),
5892
+ 'org' => array(),
5893
+ 'rec' => array(),
5894
+ 'store' => array(),
5895
+ 'tec' => array(),
5896
+ 'web' => array()),
5897
+ 'vg' => array(),
5898
+ 'vi' => array('co' => array(),
5899
+ 'com' => array(),
5900
+ 'k12' => array(),
5901
+ 'net' => array(),
5902
+ 'org' => array()),
5903
+ 'vn' => array('com' => array(),
5904
+ 'net' => array(),
5905
+ 'org' => array(),
5906
+ 'edu' => array(),
5907
+ 'gov' => array(),
5908
+ 'int' => array(),
5909
+ 'ac' => array(),
5910
+ 'biz' => array(),
5911
+ 'info' => array(),
5912
+ 'name' => array(),
5913
+ 'pro' => array(),
5914
+ 'health' => array()),
5915
+ 'vu' => array('com' => array(),
5916
+ 'edu' => array(),
5917
+ 'net' => array(),
5918
+ 'org' => array()),
5919
+ 'wf' => array(),
5920
+ 'ws' => array('com' => array(),
5921
+ 'net' => array(),
5922
+ 'org' => array(),
5923
+ 'gov' => array(),
5924
+ 'edu' => array(),
5925
+ 'dyndns' => array(),
5926
+ 'mypets' => array()),
5927
+ 'yt' => array(),
5928
+ 'امارات' => array(),
5929
+ 'বাংলা' => array(),
5930
+ '中国' => array(),
5931
+ '中國' => array(),
5932
+ 'الجزائر' => array(),
5933
+ 'مصر' => array(),
5934
+ 'გე' => array(),
5935
+ '香港' => array(),
5936
+ 'भारत' => array(),
5937
+ 'بھارت' => array(),
5938
+ 'భారత్' => array(),
5939
+ 'ભારત' => array(),
5940
+ 'ਭਾਰਤ' => array(),
5941
+ 'ভারত' => array(),
5942
+ 'இந்தியா' => array(),
5943
+ 'ایران' => array(),
5944
+ 'ايران' => array(),
5945
+ 'الاردن' => array(),
5946
+ '한국' => array(),
5947
+ 'қаз' => array(),
5948
+ 'ලංකා' => array(),
5949
+ 'இலங்கை' => array(),
5950
+ 'المغرب' => array(),
5951
+ 'мон' => array(),
5952
+ 'مليسيا' => array(),
5953
+ 'عمان' => array(),
5954
+ 'فلسطين' => array(),
5955
+ 'срб' => array('пр' => array(),
5956
+ 'орг' => array(),
5957
+ 'обр' => array(),
5958
+ 'од' => array(),
5959
+ 'упр' => array(),
5960
+ 'ак' => array()),
5961
+ 'рф' => array(),
5962
+ 'قطر' => array(),
5963
+ 'السعودية' => array(),
5964
+ 'السعودیة' => array(),
5965
+ 'السعودیۃ' => array(),
5966
+ 'السعوديه' => array(),
5967
+ 'سورية' => array(),
5968
+ 'سوريا' => array(),
5969
+ '新加坡' => array(),
5970
+ 'சிங்கப்பூர்' => array(),
5971
+ 'ไทย' => array(),
5972
+ 'تونس' => array(),
5973
+ '台灣' => array(),
5974
+ '台湾' => array(),
5975
+ '臺灣' => array(),
5976
+ 'укр' => array(),
5977
+ 'اليمن' => array(),
5978
+ 'xxx' => array(),
5979
+ 'ye' => array('*' => array()),
5980
+ 'za' => array('*' => array()),
5981
+ 'zm' => array('*' => array()),
5982
+ 'zw' => array('*' => array()),
5983
+ 'abbott' => array(),
5984
+ 'abogado' => array(),
5985
+ 'academy' => array(),
5986
+ 'accenture' => array(),
5987
+ 'accountants' => array(),
5988
+ 'active' => array(),
5989
+ 'actor' => array(),
5990
+ 'africa' => array(),
5991
+ 'agency' => array(),
5992
+ 'airforce' => array(),
5993
+ 'allfinanz' => array(),
5994
+ 'alsace' => array(),
5995
+ 'amsterdam' => array(),
5996
+ 'android' => array(),
5997
+ 'aquarelle' => array(),
5998
+ 'archi' => array(),
5999
+ 'army' => array(),
6000
+ 'associates' => array(),
6001
+ 'attorney' => array(),
6002
+ 'auction' => array(),
6003
+ 'audio' => array(),
6004
+ 'autos' => array(),
6005
+ 'axa' => array(),
6006
+ 'band' => array(),
6007
+ 'bar' => array(),
6008
+ 'barcelona' => array(),
6009
+ 'bargains' => array(),
6010
+ 'bauhaus' => array(),
6011
+ 'bayern' => array(),
6012
+ 'bcn' => array(),
6013
+ 'beer' => array(),
6014
+ 'berlin' => array(),
6015
+ 'best' => array(),
6016
+ 'bharti' => array(),
6017
+ 'bible' => array(),
6018
+ 'bid' => array(),
6019
+ 'bike' => array(),
6020
+ 'bio' => array(),
6021
+ 'black' => array(),
6022
+ 'blackfriday' => array(),
6023
+ 'bloomberg' => array(),
6024
+ 'blue' => array(),
6025
+ 'bmw' => array(),
6026
+ 'bnl' => array(),
6027
+ 'bnpparibas' => array(),
6028
+ 'bond' => array(),
6029
+ 'boo' => array(),
6030
+ 'boutique' => array(),
6031
+ 'brussels' => array(),
6032
+ 'budapest' => array(),
6033
+ 'build' => array(),
6034
+ 'builders' => array(),
6035
+ 'business' => array(),
6036
+ 'buzz' => array(),
6037
+ 'bzh' => array(),
6038
+ 'cab' => array(),
6039
+ 'cal' => array(),
6040
+ 'camera' => array(),
6041
+ 'camp' => array(),
6042
+ 'cancerresearch' => array(),
6043
+ 'capetown' => array(),
6044
+ 'capital' => array(),
6045
+ 'caravan' => array(),
6046
+ 'cards' => array(),
6047
+ 'care' => array(),
6048
+ 'career' => array(),
6049
+ 'careers' => array(),
6050
+ 'cartier' => array(),
6051
+ 'casa' => array(),
6052
+ 'cash' => array(),
6053
+ 'catering' => array(),
6054
+ 'cba' => array(),
6055
+ 'cbn' => array(),
6056
+ 'center' => array(),
6057
+ 'ceo' => array(),
6058
+ 'cern' => array(),
6059
+ 'cfa' => array(),
6060
+ 'channel' => array(),
6061
+ 'cheap' => array(),
6062
+ 'christmas' => array(),
6063
+ 'chrome' => array(),
6064
+ 'church' => array(),
6065
+ 'citic' => array(),
6066
+ 'city' => array(),
6067
+ 'claims' => array(),
6068
+ 'cleaning' => array(),
6069
+ 'click' => array(),
6070
+ 'clinic' => array(),
6071
+ 'clothing' => array(),
6072
+ 'club' => array(),
6073
+ 'codes' => array(),
6074
+ 'coffee' => array(),
6075
+ 'college' => array(),
6076
+ 'cologne' => array(),
6077
+ 'commbank' => array(),
6078
+ 'community' => array(),
6079
+ 'company' => array(),
6080
+ 'computer' => array(),
6081
+ 'condos' => array(),
6082
+ 'construction' => array(),
6083
+ 'consulting' => array(),
6084
+ 'contractors' => array(),
6085
+ 'cooking' => array(),
6086
+ 'cool' => array(),
6087
+ 'country' => array(),
6088
+ 'credit' => array(),
6089
+ 'creditcard' => array(),
6090
+ 'crs' => array(),
6091
+ 'cruises' => array(),
6092
+ 'cuisinella' => array(),
6093
+ 'cymru' => array(),
6094
+ 'dabur' => array(),
6095
+ 'dad' => array(),
6096
+ 'dance' => array(),
6097
+ 'dating' => array(),
6098
+ 'datsun' => array(),
6099
+ 'day' => array(),
6100
+ 'deals' => array(),
6101
+ 'degree' => array(),
6102
+ 'democrat' => array(),
6103
+ 'dental' => array(),
6104
+ 'dentist' => array(),
6105
+ 'desi' => array(),
6106
+ 'diamonds' => array(),
6107
+ 'diet' => array(),
6108
+ 'digital' => array(),
6109
+ 'direct' => array(),
6110
+ 'directory' => array(),
6111
+ 'discount' => array(),
6112
+ 'dnp' => array(),
6113
+ 'domains' => array(),
6114
+ 'doosan' => array(),
6115
+ 'durban' => array(),
6116
+ 'dvag' => array(),
6117
+ 'eat' => array(),
6118
+ 'education' => array(),
6119
+ 'email' => array(),
6120
+ 'emerck' => array(),
6121
+ 'engineer' => array(),
6122
+ 'engineering' => array(),
6123
+ 'enterprises' => array(),
6124
+ 'equipment' => array(),
6125
+ 'erni' => array(),
6126
+ 'esq' => array(),
6127
+ 'estate' => array(),
6128
+ 'eurovision' => array(),
6129
+ 'eus' => array(),
6130
+ 'events' => array(),
6131
+ 'everbank' => array(),
6132
+ 'exchange' => array(),
6133
+ 'expert' => array(),
6134
+ 'exposed' => array(),
6135
+ 'fail' => array(),
6136
+ 'fan' => array(),
6137
+ 'farm' => array(),
6138
+ 'fashion' => array(),
6139
+ 'feedback' => array(),
6140
+ 'finance' => array(),
6141
+ 'financial' => array(),
6142
+ 'firmdale' => array(),
6143
+ 'fish' => array(),
6144
+ 'fishing' => array(),
6145
+ 'fitness' => array(),
6146
+ 'flights' => array(),
6147
+ 'florist' => array(),
6148
+ 'flsmidth' => array(),
6149
+ 'fly' => array(),
6150
+ 'foo' => array(),
6151
+ 'forsale' => array(),
6152
+ 'foundation' => array(),
6153
+ 'frl' => array(),
6154
+ 'frogans' => array(),
6155
+ 'fund' => array(),
6156
+ 'furniture' => array(),
6157
+ 'futbol' => array(),
6158
+ 'gal' => array(),
6159
+ 'gallery' => array(),
6160
+ 'garden' => array(),
6161
+ 'gbiz' => array(),
6162
+ 'gdn' => array(),
6163
+ 'gent' => array(),
6164
+ 'ggee' => array(),
6165
+ 'gift' => array(),
6166
+ 'gifts' => array(),
6167
+ 'gives' => array(),
6168
+ 'glass' => array(),
6169
+ 'gle' => array(),
6170
+ 'global' => array(),
6171
+ 'globo' => array(),
6172
+ 'gmail' => array(),
6173
+ 'gmo' => array(),
6174
+ 'gmx' => array(),
6175
+ 'google' => array(),
6176
+ 'gop' => array(),
6177
+ 'graphics' => array(),
6178
+ 'gratis' => array(),
6179
+ 'green' => array(),
6180
+ 'gripe' => array(),
6181
+ 'group' => array(),
6182
+ 'guge' => array(),
6183
+ 'guide' => array(),
6184
+ 'guitars' => array(),
6185
+ 'guru' => array(),
6186
+ 'hamburg' => array(),
6187
+ 'haus' => array(),
6188
+ 'healthcare' => array(),
6189
+ 'help' => array(),
6190
+ 'here' => array(),
6191
+ 'hermes' => array(),
6192
+ 'hiphop' => array(),
6193
+ 'hiv' => array(),
6194
+ 'holdings' => array(),
6195
+ 'holiday' => array(),
6196
+ 'homes' => array(),
6197
+ 'horse' => array(),
6198
+ 'host' => array(),
6199
+ 'hosting' => array(),
6200
+ 'house' => array(),
6201
+ 'how' => array(),
6202
+ 'ibm' => array(),
6203
+ 'ifm' => array(),
6204
+ 'iinet' => array(),
6205
+ 'immo' => array(),
6206
+ 'immobilien' => array(),
6207
+ 'industries' => array(),
6208
+ 'infiniti' => array(),
6209
+ 'ing' => array(),
6210
+ 'ink' => array(),
6211
+ 'institute' => array(),
6212
+ 'insure' => array(),
6213
+ 'international' => array(),
6214
+ 'investments' => array(),
6215
+ 'ipiranga' => array(),
6216
+ 'irish' => array(),
6217
+ 'ist' => array(),
6218
+ 'istanbul' => array(),
6219
+ 'iwc' => array(),
6220
+ 'java' => array(),
6221
+ 'jetzt' => array(),
6222
+ 'joburg' => array(),
6223
+ 'juegos' => array(),
6224
+ 'kaufen' => array(),
6225
+ 'kim' => array(),
6226
+ 'kitchen' => array(),
6227
+ 'kiwi' => array(),
6228
+ 'koeln' => array(),
6229
+ 'krd' => array(),
6230
+ 'kred' => array(),
6231
+ 'lacaixa' => array(),
6232
+ 'land' => array(),
6233
+ 'latrobe' => array(),
6234
+ 'lawyer' => array(),
6235
+ 'lds' => array(),
6236
+ 'lease' => array(),
6237
+ 'leclerc' => array(),
6238
+ 'lgbt' => array(),
6239
+ 'life' => array(),
6240
+ 'lighting' => array(),
6241
+ 'limited' => array(),
6242
+ 'limo' => array(),
6243
+ 'link' => array(),
6244
+ 'loans' => array(),
6245
+ 'london' => array(),
6246
+ 'lotto' => array(),
6247
+ 'ltda' => array(),
6248
+ 'luxe' => array(),
6249
+ 'luxury' => array(),
6250
+ 'madrid' => array(),
6251
+ 'maison' => array(),
6252
+ 'management' => array(),
6253
+ 'mango' => array(),
6254
+ 'market' => array(),
6255
+ 'marketing' => array(),
6256
+ 'media' => array(),
6257
+ 'meet' => array(),
6258
+ 'melbourne' => array(),
6259
+ 'meme' => array(),
6260
+ 'menu' => array(),
6261
+ 'miami' => array(),
6262
+ 'mini' => array(),
6263
+ 'moda' => array(),
6264
+ 'moe' => array(),
6265
+ 'monash' => array(),
6266
+ 'montblanc' => array(),
6267
+ 'mormon' => array(),
6268
+ 'mortgage' => array(),
6269
+ 'moscow' => array(),
6270
+ 'motorcycles' => array(),
6271
+ 'mov' => array(),
6272
+ 'nagoya' => array(),
6273
+ 'navy' => array(),
6274
+ 'netbank' => array(),
6275
+ 'network' => array(),
6276
+ 'neustar' => array(),
6277
+ 'new' => array(),
6278
+ 'nexus' => array(),
6279
+ 'ngo' => array(),
6280
+ 'nhk' => array(),
6281
+ 'ninja' => array(),
6282
+ 'nissan' => array(),
6283
+ 'nra' => array(),
6284
+ 'nrw' => array(),
6285
+ 'nyc' => array(),
6286
+ 'okinawa' => array(),
6287
+ 'ong' => array(),
6288
+ 'onl' => array(),
6289
+ 'ooo' => array(),
6290
+ 'oracle' => array(),
6291
+ 'organic' => array(),
6292
+ 'otsuka' => array(),
6293
+ 'ovh' => array(),
6294
+ 'paris' => array(),
6295
+ 'partners' => array(),
6296
+ 'parts' => array(),
6297
+ 'pharmacy' => array(),
6298
+ 'photo' => array(),
6299
+ 'photography' => array(),
6300
+ 'photos' => array(),
6301
+ 'physio' => array(),
6302
+ 'pics' => array(),
6303
+ 'pictet' => array(),
6304
+ 'pictures' => array(),
6305
+ 'pink' => array(),
6306
+ 'pizza' => array(),
6307
+ 'place' => array(),
6308
+ 'plumbing' => array(),
6309
+ 'pohl' => array(),
6310
+ 'poker' => array(),
6311
+ 'praxi' => array(),
6312
+ 'press' => array(),
6313
+ 'prod' => array(),
6314
+ 'productions' => array(),
6315
+ 'prof' => array(),
6316
+ 'properties' => array(),
6317
+ 'property' => array(),
6318
+ 'pub' => array(),
6319
+ 'qpon' => array(),
6320
+ 'quebec' => array(),
6321
+ 'realtor' => array(),
6322
+ 'recipes' => array(),
6323
+ 'red' => array(),
6324
+ 'rehab' => array(),
6325
+ 'reise' => array(),
6326
+ 'reisen' => array(),
6327
+ 'ren' => array(),
6328
+ 'rentals' => array(),
6329
+ 'repair' => array(),
6330
+ 'report' => array(),
6331
+ 'republican' => array(),
6332
+ 'rest' => array(),
6333
+ 'restaurant' => array(),
6334
+ 'reviews' => array(),
6335
+ 'rich' => array(),
6336
+ 'rio' => array(),
6337
+ 'rip' => array(),
6338
+ 'rocks' => array(),
6339
+ 'rodeo' => array(),
6340
+ 'rsvp' => array(),
6341
+ 'ruhr' => array(),
6342
+ 'ryukyu' => array(),
6343
+ 'saarland' => array(),
6344
+ 'samsung' => array(),
6345
+ 'sap' => array(),
6346
+ 'sarl' => array(),
6347
+ 'sca' => array(),
6348
+ 'scb' => array(),
6349
+ 'schmidt' => array(),
6350
+ 'scholarships' => array(),
6351
+ 'schule' => array(),
6352
+ 'scot' => array(),
6353
+ 'seat' => array(),
6354
+ 'services' => array(),
6355
+ 'sew' => array(),
6356
+ 'sexy' => array(),
6357
+ 'sharp' => array(),
6358
+ 'shiksha' => array(),
6359
+ 'shoes' => array(),
6360
+ 'shriram' => array(),
6361
+ 'singles' => array(),
6362
+ 'sky' => array(),
6363
+ 'social' => array(),
6364
+ 'software' => array(),
6365
+ 'sohu' => array(),
6366
+ 'solar' => array(),
6367
+ 'solutions' => array(),
6368
+ 'soy' => array(),
6369
+ 'space' => array(),
6370
+ 'spiegel' => array(),
6371
+ 'supplies' => array(),
6372
+ 'supply' => array(),
6373
+ 'support' => array(),
6374
+ 'surf' => array(),
6375
+ 'surgery' => array(),
6376
+ 'suzuki' => array(),
6377
+ 'systems' => array(),
6378
+ 'taipei' => array(),
6379
+ 'tatar' => array(),
6380
+ 'tattoo' => array(),
6381
+ 'tax' => array(),
6382
+ 'technology' => array(),
6383
+ 'temasek' => array(),
6384
+ 'tienda' => array(),
6385
+ 'tips' => array(),
6386
+ 'tirol' => array(),
6387
+ 'today' => array(),
6388
+ 'tokyo' => array(),
6389
+ 'tools' => array(),
6390
+ 'top' => array(),
6391
+ 'toshiba' => array(),
6392
+ 'town' => array(),
6393
+ 'toys' => array(),
6394
+ 'trade' => array(),
6395
+ 'training' => array(),
6396
+ 'tui' => array(),
6397
+ 'university' => array(),
6398
+ 'uno' => array(),
6399
+ 'uol' => array(),
6400
+ 'vacations' => array(),
6401
+ 'vegas' => array(),
6402
+ 'ventures' => array(),
6403
+ 'versicherung' => array(),
6404
+ 'vet' => array(),
6405
+ 'viajes' => array(),
6406
+ 'villas' => array(),
6407
+ 'vision' => array(),
6408
+ 'vlaanderen' => array(),
6409
+ 'vodka' => array(),
6410
+ 'vote' => array(),
6411
+ 'voting' => array(),
6412
+ 'voto' => array(),
6413
+ 'voyage' => array(),
6414
+ 'wales' => array(),
6415
+ 'wang' => array(),
6416
+ 'watch' => array(),
6417
+ 'webcam' => array(),
6418
+ 'website' => array(),
6419
+ 'wed' => array(),
6420
+ 'wedding' => array(),
6421
+ 'whoswho' => array(),
6422
+ 'wien' => array(),
6423
+ 'wiki' => array(),
6424
+ 'williamhill' => array(),
6425
+ 'wme' => array(),
6426
+ 'work' => array(),
6427
+ 'works' => array(),
6428
+ 'world' => array(),
6429
+ 'wtc' => array(),
6430
+ 'wtf' => array(),
6431
+ '佛山' => array(),
6432
+ '慈善' => array(),
6433
+ '集团' => array(),
6434
+ '在线' => array(),
6435
+ '八卦' => array(),
6436
+ 'موقع' => array(),
6437
+ '公益' => array(),
6438
+ '公司' => array(),
6439
+ '移动' => array(),
6440
+ '我爱你' => array(),
6441
+ 'москва' => array(),
6442
+ 'онлайн' => array(),
6443
+ 'сайт' => array(),
6444
+ '时尚' => array(),
6445
+ '淡马锡' => array(),
6446
+ 'орг' => array(),
6447
+ '삼성' => array(),
6448
+ '商标' => array(),
6449
+ '商店' => array(),
6450
+ '商城' => array(),
6451
+ 'дети' => array(),
6452
+ '新闻' => array(),
6453
+ '中文网' => array(),
6454
+ '中信' => array(),
6455
+ '娱乐' => array(),
6456
+ '谷歌' => array(),
6457
+ '网店' => array(),
6458
+ 'संगठन' => array(),
6459
+ '网络' => array(),
6460
+ '手机' => array(),
6461
+ 'بازار' => array(),
6462
+ '政府' => array(),
6463
+ 'شبكة' => array(),
6464
+ '机构' => array(),
6465
+ '组织机构' => array(),
6466
+ 'рус' => array(),
6467
+ 'みんな' => array(),
6468
+ 'グーグル' => array(),
6469
+ '世界' => array(),
6470
+ '网址' => array(),
6471
+ '游戏' => array(),
6472
+ 'vermögensberater' => array(),
6473
+ 'vermögensberatung' => array(),
6474
+ '企业' => array(),
6475
+ '广东' => array(),
6476
+ '政务' => array(),
6477
+ 'xyz' => array(),
6478
+ 'yachts' => array(),
6479
+ 'yandex' => array(),
6480
+ 'yoga' => array(),
6481
+ 'yokohama' => array(),
6482
+ 'youtube' => array(),
6483
+ 'zip' => array(),
6484
+ 'zone' => array());
Postman/Postman-Connectivity-Test/registered-domain-libs-master/PHP/regDomain.class.php CHANGED
@@ -1,120 +1,120 @@
1
- <?php
2
-
3
- /*
4
- * Calculate the effective registered domain of a fully qualified domain name.
5
- *
6
- * <@LICENSE>
7
- * Licensed to the Apache Software Foundation (ASF) under one or more
8
- * contributor license agreements. See the NOTICE file distributed with
9
- * this work for additional information regarding copyright ownership.
10
- * The ASF licenses this file to you under the Apache License, Version 2.0
11
- * (the "License"); you may not use this file except in compliance with
12
- * the License. You may obtain a copy of the License at:
13
- *
14
- * http://www.apache.org/licenses/LICENSE-2.0
15
- *
16
- * Unless required by applicable law or agreed to in writing, software
17
- * distributed under the License is distributed on an "AS IS" BASIS,
18
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
- * See the License for the specific language governing permissions and
20
- * limitations under the License.
21
- * </@LICENSE>
22
- *
23
- * Florian Sager, 25.07.2008, sager@agitos.de, http://www.agitos.de
24
- */
25
-
26
- /*
27
- * Remove subdomains from a signing domain to get the registered domain.
28
- *
29
- * dkim-reputation.org blocks signing domains on the level of registered domains
30
- * to rate senders who use e.g. a.spamdomain.tld, b.spamdomain.tld, ... under
31
- * the most common identifier - the registered domain - finally.
32
- *
33
- * This function returns NULL if $signingDomain is TLD itself
34
- *
35
- * $signingDomain has to be provided lowercase (!)
36
- */
37
-
38
- class regDomain {
39
- /* tld tree */
40
- protected $tldTree = array();
41
-
42
- /* main function */
43
- public function getRegisteredDomain($signingDomain, $fallback = TRUE) {
44
- $signingDomainParts = explode('.', $signingDomain);
45
-
46
- $result = $this->findRegisteredDomain($signingDomainParts, $this->tldTree);
47
-
48
- if ($result===NULL || $result=="") {
49
- // this is an invalid domain name
50
- return NULL;
51
- }
52
-
53
- // assure there is at least 1 TLD in the stripped signing domain
54
- if (!strpos($result, '.')) {
55
- if ($fallback===FALSE) {
56
- return NULL;
57
- }
58
- $cnt = count($signingDomainParts);
59
- if ($cnt==1 || $signingDomainParts[$cnt-2]=="") return NULL;
60
- if (!$this->validDomainPart($signingDomainParts[$cnt-2]) || !$this->validDomainPart($signingDomainParts[$cnt-1])) return NULL;
61
- return $signingDomainParts[$cnt-2].'.'.$signingDomainParts[$cnt-1];
62
- }
63
- return $result;
64
- }
65
-
66
- /* validate parts */
67
- public function validDomainPart($domPart) {
68
- // see http://www.register.com/domain-extension-rules.rcmx
69
- $len = strlen($domPart);
70
-
71
- // not more than 63 characters
72
- if ($len>63) return FALSE;
73
-
74
- // not less than 1 characters --> there are TLD-specific rules that could be considered additionally
75
- if ($len<1) return FALSE;
76
-
77
- // Use only letters, numbers, or hyphen ("-")
78
- // not beginning or ending with a hypen (this is TLD specific, be aware!)
79
- if (!preg_match("/^([a-z0-9])(([a-z0-9-])*([a-z0-9]))*$/", $domPart)) return FALSE;
80
-
81
- return TRUE;
82
- }
83
-
84
- /* recursive helper method */
85
- public function findRegisteredDomain($remainingSigningDomainParts, &$treeNode) {
86
- $sub = array_pop($remainingSigningDomainParts);
87
-
88
- $result = NULL;
89
- if (isset($treeNode['!'])) {
90
- return '#';
91
- }
92
-
93
- if (!$this->validDomainPart($sub)) {
94
- return NULL;
95
- }
96
-
97
- if (is_array($treeNode) && array_key_exists($sub, $treeNode)) {
98
- $result = $this->findRegisteredDomain($remainingSigningDomainParts, $treeNode[$sub]);
99
- } else if (is_array($treeNode) && array_key_exists('*', $treeNode)) {
100
- $result = $this->findRegisteredDomain($remainingSigningDomainParts, $treeNode['*']);
101
- } else {
102
- return $sub;
103
- }
104
-
105
- // this is a hack 'cause PHP interpretes '' as NULL
106
- if ($result == '#') {
107
- return $sub;
108
- } else if (strlen($result)>0) {
109
- return $result.'.'.$sub;
110
- }
111
- return NULL;
112
- }
113
-
114
- /* load tld tree into object */
115
- function __construct() {
116
- /* include tld tree data */
117
- include(dirname(__FILE__) . '/effectiveTLDs.inc.php');
118
- }
119
-
120
- }
1
+ <?php
2
+
3
+ /*
4
+ * Calculate the effective registered domain of a fully qualified domain name.
5
+ *
6
+ * <@LICENSE>
7
+ * Licensed to the Apache Software Foundation (ASF) under one or more
8
+ * contributor license agreements. See the NOTICE file distributed with
9
+ * this work for additional information regarding copyright ownership.
10
+ * The ASF licenses this file to you under the Apache License, Version 2.0
11
+ * (the "License"); you may not use this file except in compliance with
12
+ * the License. You may obtain a copy of the License at:
13
+ *
14
+ * http://www.apache.org/licenses/LICENSE-2.0
15
+ *
16
+ * Unless required by applicable law or agreed to in writing, software
17
+ * distributed under the License is distributed on an "AS IS" BASIS,
18
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
+ * See the License for the specific language governing permissions and
20
+ * limitations under the License.
21
+ * </@LICENSE>
22
+ *
23
+ * Florian Sager, 25.07.2008, sager@agitos.de, http://www.agitos.de
24
+ */
25
+
26
+ /*
27
+ * Remove subdomains from a signing domain to get the registered domain.
28
+ *
29
+ * dkim-reputation.org blocks signing domains on the level of registered domains
30
+ * to rate senders who use e.g. a.spamdomain.tld, b.spamdomain.tld, ... under
31
+ * the most common identifier - the registered domain - finally.
32
+ *
33
+ * This function returns NULL if $signingDomain is TLD itself
34
+ *
35
+ * $signingDomain has to be provided lowercase (!)
36
+ */
37
+
38
+ class regDomain {
39
+ /* tld tree */
40
+ protected $tldTree = array();
41
+
42
+ /* main function */
43
+ public function getRegisteredDomain($signingDomain, $fallback = TRUE) {
44
+ $signingDomainParts = explode('.', $signingDomain);
45
+
46
+ $result = $this->findRegisteredDomain($signingDomainParts, $this->tldTree);
47
+
48
+ if ($result===NULL || $result=="") {
49
+ // this is an invalid domain name
50
+ return NULL;
51
+ }
52
+
53
+ // assure there is at least 1 TLD in the stripped signing domain
54
+ if (!strpos($result, '.')) {
55
+ if ($fallback===FALSE) {
56
+ return NULL;
57
+ }
58
+ $cnt = count($signingDomainParts);
59
+ if ($cnt==1 || $signingDomainParts[$cnt-2]=="") return NULL;
60
+ if (!$this->validDomainPart($signingDomainParts[$cnt-2]) || !$this->validDomainPart($signingDomainParts[$cnt-1])) return NULL;
61
+ return $signingDomainParts[$cnt-2].'.'.$signingDomainParts[$cnt-1];
62
+ }
63
+ return $result;
64
+ }
65
+
66
+ /* validate parts */
67
+ public function validDomainPart($domPart) {
68
+ // see http://www.register.com/domain-extension-rules.rcmx
69
+ $len = strlen($domPart);
70
+
71
+ // not more than 63 characters
72
+ if ($len>63) return FALSE;
73
+
74
+ // not less than 1 characters --> there are TLD-specific rules that could be considered additionally
75
+ if ($len<1) return FALSE;
76
+
77
+ // Use only letters, numbers, or hyphen ("-")
78
+ // not beginning or ending with a hypen (this is TLD specific, be aware!)
79
+ if (!preg_match("/^([a-z0-9])(([a-z0-9-])*([a-z0-9]))*$/", $domPart)) return FALSE;
80
+
81
+ return TRUE;
82
+ }
83
+
84
+ /* recursive helper method */
85
+ public function findRegisteredDomain($remainingSigningDomainParts, &$treeNode) {
86
+ $sub = array_pop($remainingSigningDomainParts);
87
+
88
+ $result = NULL;
89
+ if (isset($treeNode['!'])) {
90
+ return '#';
91
+ }
92
+
93
+ if (!$this->validDomainPart($sub)) {
94
+ return NULL;
95
+ }
96
+
97
+ if (is_array($treeNode) && array_key_exists($sub, $treeNode)) {
98
+ $result = $this->findRegisteredDomain($remainingSigningDomainParts, $treeNode[$sub]);
99
+ } else if (is_array($treeNode) && array_key_exists('*', $treeNode)) {
100
+ $result = $this->findRegisteredDomain($remainingSigningDomainParts, $treeNode['*']);
101
+ } else {
102
+ return $sub;
103
+ }
104
+
105
+ // this is a hack 'cause PHP interpretes '' as NULL
106
+ if ($result == '#') {
107
+ return $sub;
108
+ } else if (strlen($result)>0) {
109
+ return $result.'.'.$sub;
110
+ }
111
+ return NULL;
112
+ }
113
+
114
+ /* load tld tree into object */
115
+ function __construct() {
116
+ /* include tld tree data */
117
+ include(dirname(__FILE__) . '/effectiveTLDs.inc.php');
118
+ }
119
+
120
+ }
Postman/Postman-Connectivity-Test/registered-domain-libs-master/PHP/regDomain.inc.php CHANGED
@@ -1,62 +1,62 @@
1
- <?php
2
-
3
- /*
4
- * Calculate the effective registered domain of a fully qualified domain name.
5
- *
6
- * <@LICENSE>
7
- * Licensed to the Apache Software Foundation (ASF) under one or more
8
- * contributor license agreements. See the NOTICE file distributed with
9
- * this work for additional information regarding copyright ownership.
10
- * The ASF licenses this file to you under the Apache License, Version 2.0
11
- * (the "License"); you may not use this file except in compliance with
12
- * the License. You may obtain a copy of the License at:
13
- *
14
- * http://www.apache.org/licenses/LICENSE-2.0
15
- *
16
- * Unless required by applicable law or agreed to in writing, software
17
- * distributed under the License is distributed on an "AS IS" BASIS,
18
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
- * See the License for the specific language governing permissions and
20
- * limitations under the License.
21
- * </@LICENSE>
22
- *
23
- * Florian Sager, 25.07.2008, sager@agitos.de, http://www.agitos.de
24
- */
25
-
26
- /*
27
- * Remove subdomains from a signing domain to get the registered domain.
28
- *
29
- * dkim-reputation.org blocks signing domains on the level of registered domains
30
- * to rate senders who use e.g. a.spamdomain.tld, b.spamdomain.tld, ... under
31
- * the most common identifier - the registered domain - finally.
32
- *
33
- * This function returns NULL if $signingDomain is TLD itself
34
- *
35
- * $signingDomain has to be provided lowercase (!)
36
- */
37
-
38
- /* pull in class */
39
- require_once (dirname ( __FILE__ ) . '/regDomain.class.php');
40
-
41
- /* create global object */
42
- ;
43
- function getRegisteredDomain($signingDomain, $fallback = TRUE) {
44
- /* pull in object */
45
- $regDomainObj = new regDomain ();
46
- /* return object method */
47
- return $regDomainObj->getRegisteredDomain ( $signingDomain, $fallback );
48
- }
49
- function validDomainPart($domPart) {
50
- /* pull in object */
51
- $regDomainObj = new regDomain ();
52
- /* return object method */
53
- return $regDomainObj->validDomainPart ( $domPart );
54
- }
55
-
56
- // recursive helper method
57
- function findRegisteredDomain($remainingSigningDomainParts, &$treeNode) {
58
- /* pull in object */
59
- $regDomainObj = new regDomain ();
60
- /* return object method */
61
- return $regDomainObj->findRegisteredDomain ( $remainingSigningDomainParts, $treeNode );
62
- }
1
+ <?php
2
+
3
+ /*
4
+ * Calculate the effective registered domain of a fully qualified domain name.
5
+ *
6
+ * <@LICENSE>
7
+ * Licensed to the Apache Software Foundation (ASF) under one or more
8
+ * contributor license agreements. See the NOTICE file distributed with
9
+ * this work for additional information regarding copyright ownership.
10
+ * The ASF licenses this file to you under the Apache License, Version 2.0
11
+ * (the "License"); you may not use this file except in compliance with
12
+ * the License. You may obtain a copy of the License at:
13
+ *
14
+ * http://www.apache.org/licenses/LICENSE-2.0
15
+ *
16
+ * Unless required by applicable law or agreed to in writing, software
17
+ * distributed under the License is distributed on an "AS IS" BASIS,
18
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
+ * See the License for the specific language governing permissions and
20
+ * limitations under the License.
21
+ * </@LICENSE>
22
+ *
23
+ * Florian Sager, 25.07.2008, sager@agitos.de, http://www.agitos.de
24
+ */
25
+
26
+ /*
27
+ * Remove subdomains from a signing domain to get the registered domain.
28
+ *
29
+ * dkim-reputation.org blocks signing domains on the level of registered domains
30
+ * to rate senders who use e.g. a.spamdomain.tld, b.spamdomain.tld, ... under
31
+ * the most common identifier - the registered domain - finally.
32
+ *
33
+ * This function returns NULL if $signingDomain is TLD itself
34
+ *
35
+ * $signingDomain has to be provided lowercase (!)
36
+ */
37
+
38
+ /* pull in class */
39
+ require_once (dirname ( __FILE__ ) . '/regDomain.class.php');
40
+
41
+ /* create global object */
42
+ ;
43
+ function getRegisteredDomain($signingDomain, $fallback = TRUE) {
44
+ /* pull in object */
45
+ $regDomainObj = new regDomain ();
46
+ /* return object method */
47
+ return $regDomainObj->getRegisteredDomain ( $signingDomain, $fallback );
48
+ }
49
+ function validDomainPart($domPart) {
50
+ /* pull in object */
51
+ $regDomainObj = new regDomain ();
52
+ /* return object method */
53
+ return $regDomainObj->validDomainPart ( $domPart );
54
+ }
55
+
56
+ // recursive helper method
57
+ function findRegisteredDomain($remainingSigningDomainParts, &$treeNode) {
58
+ /* pull in object */
59
+ $regDomainObj = new regDomain ();
60
+ /* return object method */
61
+ return $regDomainObj->findRegisteredDomain ( $remainingSigningDomainParts, $treeNode );
62
+ }
Postman/Postman-Connectivity-Test/registered-domain-libs-master/PHP/test-regDomain.php CHANGED
@@ -1,51 +1,51 @@
1
- <?php
2
-
3
- /*
4
- * Calculate the effective registered domain of a fully qualified domain name.
5
- *
6
- * <@LICENSE>
7
- * Licensed to the Apache Software Foundation (ASF) under one or more
8
- * contributor license agreements. See the NOTICE file distributed with
9
- * this work for additional information regarding copyright ownership.
10
- * The ASF licenses this file to you under the Apache License, Version 2.0
11
- * (the "License"); you may not use this file except in compliance with
12
- * the License. You may obtain a copy of the License at:
13
- *
14
- * http://www.apache.org/licenses/LICENSE-2.0
15
- *
16
- * Unless required by applicable law or agreed to in writing, software
17
- * distributed under the License is distributed on an "AS IS" BASIS,
18
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
- * See the License for the specific language governing permissions and
20
- * limitations under the License.
21
- * </@LICENSE>
22
- *
23
- * Florian Sager, 25.07.2008, sager@agitos.de, http://www.agitos.de
24
- */
25
-
26
- require_once("effectiveTLDs.inc.php");
27
- require_once("regDomain.inc.php");
28
-
29
- if ($_SERVER["argc"]<2) {
30
- print("test-regDomain.php <(fully-qualified-domain-name )+>\n");
31
- exit;
32
- }
33
-
34
- // strip subdomains from every signing domain
35
- // char dom[] = "sub2.sub.registered.nom.ad";
36
-
37
- $argc = $_SERVER["argc"];
38
- $argv = $_SERVER["argv"];
39
-
40
- for ($i=1; $i<$argc; $i++) {
41
-
42
- $registeredDomain = getRegisteredDomain($argv[$i], $tldTree);
43
-
44
- if ( $registeredDomain === NULL ) {
45
- printf("error: %s\n", $argv[$i]);
46
- } else {
47
- printf("%s\n", $registeredDomain);
48
- }
49
- }
50
-
51
- ?>
1
+ <?php
2
+
3
+ /*
4
+ * Calculate the effective registered domain of a fully qualified domain name.
5
+ *
6
+ * <@LICENSE>
7
+ * Licensed to the Apache Software Foundation (ASF) under one or more
8
+ * contributor license agreements. See the NOTICE file distributed with
9
+ * this work for additional information regarding copyright ownership.
10
+ * The ASF licenses this file to you under the Apache License, Version 2.0
11
+ * (the "License"); you may not use this file except in compliance with
12
+ * the License. You may obtain a copy of the License at:
13
+ *
14
+ * http://www.apache.org/licenses/LICENSE-2.0
15
+ *
16
+ * Unless required by applicable law or agreed to in writing, software
17
+ * distributed under the License is distributed on an "AS IS" BASIS,
18
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
+ * See the License for the specific language governing permissions and
20
+ * limitations under the License.
21
+ * </@LICENSE>
22
+ *
23
+ * Florian Sager, 25.07.2008, sager@agitos.de, http://www.agitos.de
24
+ */
25
+
26
+ require_once("effectiveTLDs.inc.php");
27
+ require_once("regDomain.inc.php");
28
+
29
+ if ($_SERVER["argc"]<2) {
30
+ print("test-regDomain.php <(fully-qualified-domain-name )+>\n");
31
+ exit;
32
+ }
33
+
34
+ // strip subdomains from every signing domain
35
+ // char dom[] = "sub2.sub.registered.nom.ad";
36
+
37
+ $argc = $_SERVER["argc"];
38
+ $argv = $_SERVER["argv"];
39
+
40
+ for ($i=1; $i<$argc; $i++) {
41
+
42
+ $registeredDomain = getRegisteredDomain($argv[$i], $tldTree);
43
+
44
+ if ( $registeredDomain === NULL ) {
45
+ printf("error: %s\n", $argv[$i]);
46
+ } else {
47
+ printf("%s\n", $registeredDomain);
48
+ }
49
+ }
50
+
51
+ ?>
Postman/Postman-Connectivity-Test/registered-domain-libs-master/README.txt CHANGED
@@ -1,56 +1,56 @@
1
- ===============================================
2
- Detection of registered domains by reg-dom libs
3
- ===============================================
4
-
5
- The reg-dom libs are available in C, Perl and PHP so far.
6
-
7
- They include recent representations of the effective TLD list available at
8
- http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1
9
- and help to convert an arbitrary domain name to the registered domain name.
10
-
11
- Sample use:
12
- dkim-reputation.org blocks signing domains on the level of registered domains
13
- to rate senders who use e.g. a.spamdomain.tld, b.spamdomain.tld, ... under
14
- the most common identifier - the registered domain - finally.
15
- Project page: http://www.dkim-reputation.org/regdom-libs/
16
-
17
- Pseudo code:
18
- registeredDomain = getRegisteredDomain(ingoingDomain);
19
-
20
- Return values:
21
- 1) NULL if ingoingDomain is a TLD
22
- 2) the registered domain name if TLD is known
23
- 3) just <domain>.<tld> if <tld> is unknown
24
- This case was added to support new TLDs in outdated reg-dom libs
25
- by a certain likelihood. This fallback method is implemented in the
26
- last conversion step and can be simply commented out.
27
-
28
- ---
29
-
30
- If you like to regenerate the effective TLD tree structure by yourself
31
- you can use the script generateEffectiveTLDs.php with the following parameters:
32
-
33
- php generateEffectiveTLDs.php php > PHP/effectiveTLDs.inc.php
34
- php generateEffectiveTLDs.php perl > Perl/effectiveTLDs.pm
35
- php generateEffectiveTLDs.php c > C/tld-canon.h
36
-
37
-
38
-
39
- # Licensed to the Apache Software Foundation (ASF) under one or more
40
- # contributor license agreements. See the NOTICE file distributed with
41
- # this work for additional information regarding copyright ownership.
42
- # The ASF licenses this file to you under the Apache License, Version 2.0
43
- # (the "License"); you may not use this file except in compliance with
44
- # the License. You may obtain a copy of the License at:
45
- #
46
- # http://www.apache.org/licenses/LICENSE-2.0
47
- #
48
- # Unless required by applicable law or agreed to in writing, software
49
- # distributed under the License is distributed on an "AS IS" BASIS,
50
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
51
- # See the License for the specific language governing permissions and
52
- # limitations under the License.
53
- # </@LICENSE>
54
-
55
-
56
- Florian Sager, 2009-02-05, sager@agitos.de, http://www.agitos.de
1
+ ===============================================
2
+ Detection of registered domains by reg-dom libs
3
+ ===============================================
4
+
5
+ The reg-dom libs are available in C, Perl and PHP so far.
6
+
7
+ They include recent representations of the effective TLD list available at
8
+ http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1
9
+ and help to convert an arbitrary domain name to the registered domain name.
10
+
11
+ Sample use:
12
+ dkim-reputation.org blocks signing domains on the level of registered domains
13
+ to rate senders who use e.g. a.spamdomain.tld, b.spamdomain.tld, ... under
14
+ the most common identifier - the registered domain - finally.
15
+ Project page: http://www.dkim-reputation.org/regdom-libs/
16
+
17
+ Pseudo code:
18
+ registeredDomain = getRegisteredDomain(ingoingDomain);
19
+
20
+ Return values:
21
+ 1) NULL if ingoingDomain is a TLD
22
+ 2) the registered domain name if TLD is known
23
+ 3) just <domain>.<tld> if <tld> is unknown
24
+ This case was added to support new TLDs in outdated reg-dom libs
25
+ by a certain likelihood. This fallback method is implemented in the
26
+ last conversion step and can be simply commented out.
27
+
28
+ ---
29
+
30
+ If you like to regenerate the effective TLD tree structure by yourself
31
+ you can use the script generateEffectiveTLDs.php with the following parameters:
32
+
33
+ php generateEffectiveTLDs.php php > PHP/effectiveTLDs.inc.php
34
+ php generateEffectiveTLDs.php perl > Perl/effectiveTLDs.pm
35
+ php generateEffectiveTLDs.php c > C/tld-canon.h
36
+
37
+
38
+
39
+ # Licensed to the Apache Software Foundation (ASF) under one or more
40
+ # contributor license agreements. See the NOTICE file distributed with
41
+ # this work for additional information regarding copyright ownership.
42
+ # The ASF licenses this file to you under the Apache License, Version 2.0
43
+ # (the "License"); you may not use this file except in compliance with
44
+ # the License. You may obtain a copy of the License at:
45
+ #
46
+ # http://www.apache.org/licenses/LICENSE-2.0
47
+ #
48
+ # Unless required by applicable law or agreed to in writing, software
49
+ # distributed under the License is distributed on an "AS IS" BASIS,
50
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
51
+ # See the License for the specific language governing permissions and
52
+ # limitations under the License.
53
+ # </@LICENSE>
54
+
55
+
56
+ Florian Sager, 2009-02-05, sager@agitos.de, http://www.agitos.de
Postman/Postman-Connectivity-Test/registered-domain-libs-master/generateEffectiveTLDs.php CHANGED
@@ -1,213 +1,213 @@
1
- <?php
2
-
3
- /*
4
- * Florian Sager, 06.08.2008, sager@agitos.de, http://www.agitos.de
5
- *
6
- * Auto-Generate PHP array tree that contains all TLDs from the URL (see below);
7
- * The output has to be copied to reputation-libs/effectiveTLDs.inc.php
8
- *
9
- *
10
- */
11
-
12
- header('Content-Type: text/html; charset=utf-8');
13
-
14
- DEFINE('URL', 'http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1');
15
-
16
- $format = "php";
17
- if ($_SERVER['argc']>1) {
18
- if ($_SERVER['argv'][1] == "perl") {
19
- $format = "perl";
20
- } else if ($_SERVER['argv'][1] == "c") {
21
- $format = "c";
22
- }
23
- }
24
-
25
- /*
26
- * Does $search start with $startstring?
27
- */
28
- function startsWith($search, $startstring) {
29
- return (substr($search, 0, strlen($startstring))==$startstring);
30
- }
31
-
32
- /*
33
- * Does $search end with $endstring?
34
- */
35
- function endsWith($search, $endstring) {
36
- return (substr($search, -strlen($endstring))==$endstring);
37
- }
38
-
39
-
40
- function buildSubdomain(&$node, $tldParts) {
41
-
42
- $dom = trim(array_pop($tldParts));
43
-
44
- $isNotDomain = FALSE;
45
- if (startsWith($dom, "!")) {
46
- $dom = substr($dom, 1);
47
- $isNotDomain = TRUE;
48
- }
49
-
50
- if (!array_key_exists($dom, $node)) {
51
- if ($isNotDomain) {
52
- $node[$dom] = array("!" => "");
53
- } else {
54
- $node[$dom] = array();
55
- }
56
- }
57
-
58
- if (!$isNotDomain && count($tldParts)>0) {
59
- buildSubdomain($node[$dom], $tldParts);
60
- }
61
- }
62
-
63
- function printNode($key, $valueTree, $isAssignment = false) {
64
-
65
- global $format;
66
-
67
- if ($isAssignment) {
68
- if ($format == "perl") {
69
- echo "$key = {";
70
- } else {
71
- echo "$key = array(";
72
- }
73
- } else {
74
- if (strcmp($key, "!")==0) {
75
- if ($format == "perl") {
76
- echo "'!' => {}";
77
- } else {
78
- echo "'!' => ''";
79
- }
80
- return;
81
- } else {
82
- if ($format == "perl") {
83
- echo "'$key' => {";
84
- } else {
85
- echo "'$key' => array(";
86
- }
87
- }
88
- }
89
-
90
- $keys = array_keys($valueTree);
91
-
92
- for ($i=0; $i<count($keys); $i++) {
93
-
94
- $key = $keys[$i];
95
-
96
- printNode($key, $valueTree[$key]);
97
-
98
- if ($i+1 != count($valueTree)) {
99
- echo ",\n";
100
- } else {
101
- "\n";
102
- }
103
- }
104
-
105
- if ($format == "perl") {
106
- echo '}';
107
- } else {
108
- echo ')';
109
- }
110
- }
111
-
112
- // sample: root(3:ac(5:com,edu,gov,net,ad(3:nom,co!,*)),de,com)
113
-
114
- function printNode_C($key, $valueTree) {
115
-
116
- echo "$key";
117
-
118
- $keys = array_keys($valueTree);
119
-
120
- if (count($keys)>0) {
121
-
122
- if (strcmp($keys['!'], "!")==0) {
123
- echo "!";
124
- } else {
125
-
126
- echo "(".count($keys).":";
127
-
128
- for ($i=0; $i<count($keys); $i++) {
129
-
130
- $key = $keys[$i];
131
-
132
- // if (count($valueTree[$key])>0) {
133
- printNode_C($key, $valueTree[$key]);
134
- // }
135
-
136
- if ($i+1 != count($valueTree)) {
137
- echo ",";
138
- }
139
- }
140
-
141
- echo ')';
142
- }
143
- }
144
- }
145
-
146
- // --- main ---
147
-
148
- error_reporting(E_ERROR);
149
-
150
- $tldTree = array();
151
- $list = file_get_contents(URL);
152
- // $list = "bg\na.bg\n0.bg\n!c.bg\n";
153
- $lines = explode("\n", $list);
154
- $licence = TRUE;
155
-
156
- if ($format == "php") echo "<?php\n";
157
-
158
- foreach ($lines as $line) {
159
- $line = trim($line);
160
- if ($line == "") {
161
- if ($licence) {
162
- $licence = FALSE;
163
- echo "\n";
164
- }
165
- continue;
166
- }
167
- if (startsWith($line, "//")) {
168
- if ($licence) {
169
- if ($format == "perl") {
170
- echo "# ".substr($line, 2)."\n";
171
- } else {
172
- echo $line."\n";
173
- }
174
- }
175
- continue;
176
- }
177
-
178
- // this must be a TLD
179
- $tldParts = preg_split('\.', $line);
180
- buildSubdomain($tldTree, $tldParts);
181
- }
182
-
183
- // print_r($tldTree);
184
-
185
- /*
186
- $tldTree = array(
187
- 'de' => array(), // test.agitos.de --> agitos.de
188
- 'uk' => array(
189
- 'co' => array(), // test.agitos.co.uk --> agitos.co.uk
190
- 'xy' => array('!'), // test.agitos.xy.uk --> xy.uk
191
- '*' => array() // test.agitos.ab.uk --> agitos.ab.uk
192
- )
193
- );
194
- */
195
-
196
- if ($format == "c") {
197
-
198
- echo "static const char tldString[] = \"";
199
- printNode_C("root", $tldTree);
200
- echo "\";\n\n";
201
-
202
- } else {
203
-
204
- if ($format == "perl") {
205
- print "package effectiveTLDs;\n\n";
206
- }
207
- printNode("\$tldTree", $tldTree, TRUE);
208
- echo ";\n";
209
- if ($format == "php") echo '?>' . "\n";
210
-
211
- }
212
-
213
- ?>
1
+ <?php
2
+
3
+ /*
4
+ * Florian Sager, 06.08.2008, sager@agitos.de, http://www.agitos.de
5
+ *
6
+ * Auto-Generate PHP array tree that contains all TLDs from the URL (see below);
7
+ * The output has to be copied to reputation-libs/effectiveTLDs.inc.php
8
+ *
9
+ *
10
+ */
11
+
12
+ header('Content-Type: text/html; charset=utf-8');
13
+
14
+ DEFINE('URL', 'http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1');
15
+
16
+ $format = "php";
17
+ if ($_SERVER['argc']>1) {
18
+ if ($_SERVER['argv'][1] == "perl") {
19
+ $format = "perl";
20
+ } else if ($_SERVER['argv'][1] == "c") {
21
+ $format = "c";
22
+ }
23
+ }
24
+
25
+ /*
26
+ * Does $search start with $startstring?
27
+ */
28
+ function startsWith($search, $startstring) {
29
+ return (substr($search, 0, strlen($startstring))==$startstring);
30
+ }
31
+
32
+ /*
33
+ * Does $search end with $endstring?
34
+ */
35
+ function endsWith($search, $endstring) {
36
+ return (substr($search, -strlen($endstring))==$endstring);
37
+ }
38
+
39
+
40
+ function buildSubdomain(&$node, $tldParts) {
41
+
42
+ $dom = trim(array_pop($tldParts));
43
+
44
+ $isNotDomain = FALSE;
45
+ if (startsWith($dom, "!")) {
46
+ $dom = substr($dom, 1);
47
+ $isNotDomain = TRUE;
48
+ }
49
+
50
+ if (!array_key_exists($dom, $node)) {
51
+ if ($isNotDomain) {
52
+ $node[$dom] = array("!" => "");
53
+ } else {
54
+ $node[$dom] = array();
55
+ }
56
+ }
57
+
58
+ if (!$isNotDomain && count($tldParts)>0) {
59
+ buildSubdomain($node[$dom], $tldParts);
60
+ }
61
+ }
62
+
63
+ function printNode($key, $valueTree, $isAssignment = false) {
64
+
65
+ global $format;
66
+
67
+ if ($isAssignment) {
68
+ if ($format == "perl") {
69
+ echo "$key = {";
70
+ } else {
71
+ echo "$key = array(";
72
+ }
73
+ } else {
74
+ if (strcmp($key, "!")==0) {
75
+ if ($format == "perl") {
76
+ echo "'!' => {}";
77
+ } else {
78
+ echo "'!' => ''";
79
+ }
80
+ return;
81
+ } else {
82
+ if ($format == "perl") {
83
+ echo "'$key' => {";
84
+ } else {
85
+ echo "'$key' => array(";
86
+ }
87
+ }
88
+ }
89
+
90
+ $keys = array_keys($valueTree);
91
+
92
+ for ($i=0; $i<count($keys); $i++) {
93
+
94
+ $key = $keys[$i];
95
+
96
+ printNode($key, $valueTree[$key]);
97
+
98
+ if ($i+1 != count($valueTree)) {
99
+ echo ",\n";
100
+ } else {
101
+ "\n";
102
+ }
103
+ }
104
+
105
+ if ($format == "perl") {
106
+ echo '}';
107
+ } else {
108
+ echo ')';
109
+ }
110
+ }
111
+
112
+ // sample: root(3:ac(5:com,edu,gov,net,ad(3:nom,co!,*)),de,com)
113
+
114
+ function printNode_C($key, $valueTree) {
115
+
116
+ echo "$key";
117
+
118
+ $keys = array_keys($valueTree);
119
+
120
+ if (count($keys)>0) {
121
+
122
+ if (strcmp($keys['!'], "!")==0) {
123
+ echo "!";
124
+ } else {
125
+
126
+ echo "(".count($keys).":";
127
+
128
+ for ($i=0; $i<count($keys); $i++) {
129
+
130
+ $key = $keys[$i];
131
+
132
+ // if (count($valueTree[$key])>0) {
133
+ printNode_C($key, $valueTree[$key]);
134
+ // }
135
+
136
+ if ($i+1 != count($valueTree)) {
137
+ echo ",";
138
+ }
139
+ }
140
+
141
+ echo ')';
142
+ }
143
+ }
144
+ }
145
+
146
+ // --- main ---
147
+
148
+ error_reporting(E_ERROR);
149
+
150
+ $tldTree = array();
151
+ $list = file_get_contents(URL);
152
+ // $list = "bg\na.bg\n0.bg\n!c.bg\n";
153
+ $lines = explode("\n", $list);
154
+ $licence = TRUE;
155
+
156
+ if ($format == "php") echo "<?php\n";
157
+
158
+ foreach ($lines as $line) {
159
+ $line = trim($line);
160
+ if ($line == "") {
161
+ if ($licence) {
162
+ $licence = FALSE;
163
+ echo "\n";
164
+ }
165
+ continue;
166
+ }
167
+ if (startsWith($line, "//")) {
168
+ if ($licence) {
169
+ if ($format == "perl") {
170
+ echo "# ".substr($line, 2)."\n";
171
+ } else {
172
+ echo $line."\n";
173
+ }
174
+ }
175
+ continue;
176
+ }
177
+
178
+ // this must be a TLD
179
+ $tldParts = preg_split('\.', $line);
180
+ buildSubdomain($tldTree, $tldParts);
181
+ }
182
+
183
+ // print_r($tldTree);
184
+
185
+ /*
186
+ $tldTree = array(
187
+ 'de' => array(), // test.agitos.de --> agitos.de
188
+ 'uk' => array(
189
+ 'co' => array(), // test.agitos.co.uk --> agitos.co.uk
190
+ 'xy' => array('!'), // test.agitos.xy.uk --> xy.uk
191
+ '*' => array() // test.agitos.ab.uk --> agitos.ab.uk
192
+ )
193
+ );
194
+ */
195
+
196
+ if ($format == "c") {
197
+
198
+ echo "static const char tldString[] = \"";
199
+ printNode_C("root", $tldTree);
200
+ echo "\";\n\n";
201
+
202
+ } else {
203
+
204
+ if ($format == "perl") {
205
+ print "package effectiveTLDs;\n\n";
206
+ }
207
+ printNode("\$tldTree", $tldTree, TRUE);
208
+ echo ";\n";
209
+ if ($format == "php") echo '?>' . "\n";
210
+
211
+ }
212
+
213
+ ?>
Postman/Postman-Controller/PostmanAdminPointer.php CHANGED
@@ -1,116 +1,116 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- if (! class_exists ( 'PostmanAdminPointer' )) {
7
-
8
- /**
9
- * From http://code.tutsplus.com/articles/integrating-with-wordpress-ui-admin-pointers--wp-26853
10
- *
11
- * @author jasonhendriks
12
- *
13
- */
14
- class PostmanAdminPointer {
15
- private $logger;
16
- private $rootPluginFilenameAndPath;
17
-
18
- /**
19
- *
20
- * @param mixed $rootPluginFilenameAndPath
21
- */
22
- function __construct($rootPluginFilenameAndPath) {
23
- $this->logger = new PostmanLogger ( get_class ( $this ) );
24
- $this->rootPluginFilenameAndPath = $rootPluginFilenameAndPath;
25
-
26
- // Don't run on WP < 3.3
27
- if (get_bloginfo ( 'version' ) < '3.3' || true)
28
- return;
29
-
30
- add_action ( 'admin_enqueue_scripts', array (
31
- $this,
32
- 'wptuts_pointer_load'
33
- ), 1000 );
34
- add_filter ( 'postman_admin_pointers-settings_page_postman', array (
35
- $this,
36
- 'wptuts_register_pointer_testing'
37
- ) );
38
- }
39
-
40
- /**
41
- *
42
- * @param mixed $hook_suffix
43
- */
44
- function wptuts_pointer_load($hook_suffix) {
45
- // only do this for administrators
46
- if (PostmanUtils::isAdmin ()) {
47
- $this->logger->trace ( 'wptuts' );
48
-
49
- $screen = get_current_screen ();
50
- $screen_id = $screen->id;
51
-
52
- // Get pointers for this screen
53
- $pointers = apply_filters ( 'postman_admin_pointers-' . $screen_id, array () );
54
-
55
- if (! $pointers || ! is_array ( $pointers ))
56
- return;
57
-
58
- // Get dismissed pointers
59
- $dismissed = explode ( ',', ( string ) get_user_meta ( get_current_user_id (), 'dismissed_wp_pointers', true ) );
60
- $this->logger->trace ( $dismissed );
61
- $valid_pointers = array ();
62
-
63
- // Check pointers and remove dismissed ones.
64
- foreach ( $pointers as $pointer_id => $pointer ) {
65
-
66
- // Sanity check
67
- if (in_array ( $pointer_id, $dismissed ) || empty ( $pointer ) || empty ( $pointer_id ) || empty ( $pointer ['target'] ) || empty ( $pointer ['options'] ))
68
- continue;
69
-
70
- $pointer ['pointer_id'] = $pointer_id;
71
-
72
- // Add the pointer to $valid_pointers array
73
- $valid_pointers ['pointers'] [] = $pointer;
74
- }
75
-
76
- // No valid pointers? Stop here.
77
- if (empty ( $valid_pointers )) {
78
- return;
79
- }
80
-
81
- // Add pointers style to queue.
82
- wp_enqueue_style ( 'wp-pointer' );
83
-
84
- // Add pointers script to queue. Add custom script.
85
- /**
86
- * @todo Check if this work
87
- */
88
- /*
89
- wp_enqueue_script ( 'postman_admin_pointer', plugins_url ( 'script/postman-admin-pointer.js', $this->rootPluginFilenameAndPath ), array (
90
- 'wp-pointer'
91
- ) );
92
-
93
- // Add pointer options to script.
94
- wp_localize_script ( 'postman_admin_pointer', 'postman_admin_pointer', $valid_pointers );
95
- */
96
- $this->logger->trace ( 'out wptuts' );
97
- }
98
- }
99
- function wptuts_register_pointer_testing($p) {
100
- // only do this for administrators
101
- if (PostmanUtils::isAdmin () && false) {
102
- $p ['postman16_log'] = array (
103
- 'target' => '.configure_manually',
104
- 'options' => array (
105
- 'content' => '',
106
- 'position' => array (
107
- 'edge' => 'top',
108
- 'align' => 'left'
109
- )
110
- )
111
- );
112
- return $p;
113
- }
114
- }
115
- }
116
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ if (! class_exists ( 'PostmanAdminPointer' )) {
7
+
8
+ /**
9
+ * From http://code.tutsplus.com/articles/integrating-with-wordpress-ui-admin-pointers--wp-26853
10
+ *
11
+ * @author jasonhendriks
12
+ *
13
+ */
14
+ class PostmanAdminPointer {
15
+ private $logger;
16
+ private $rootPluginFilenameAndPath;
17
+
18
+ /**
19
+ *
20
+ * @param mixed $rootPluginFilenameAndPath
21
+ */
22
+ function __construct($rootPluginFilenameAndPath) {
23
+ $this->logger = new PostmanLogger ( get_class ( $this ) );
24
+ $this->rootPluginFilenameAndPath = $rootPluginFilenameAndPath;
25
+
26
+ // Don't run on WP < 3.3
27
+ if (get_bloginfo ( 'version' ) < '3.3' || true)
28
+ return;
29
+
30
+ add_action ( 'admin_enqueue_scripts', array (
31
+ $this,
32
+ 'wptuts_pointer_load'
33
+ ), 1000 );
34
+ add_filter ( 'postman_admin_pointers-settings_page_postman', array (
35
+ $this,
36
+ 'wptuts_register_pointer_testing'
37
+ ) );
38
+ }
39
+
40
+ /**
41
+ *
42
+ * @param mixed $hook_suffix
43
+ */
44
+ function wptuts_pointer_load($hook_suffix) {
45
+ // only do this for administrators
46
+ if (PostmanUtils::isAdmin ()) {
47
+ $this->logger->trace ( 'wptuts' );
48
+
49
+ $screen = get_current_screen ();
50
+ $screen_id = $screen->id;
51
+
52
+ // Get pointers for this screen
53
+ $pointers = apply_filters ( 'postman_admin_pointers-' . $screen_id, array () );
54
+
55
+ if (! $pointers || ! is_array ( $pointers ))
56
+ return;
57
+
58
+ // Get dismissed pointers
59
+ $dismissed = explode ( ',', ( string ) get_user_meta ( get_current_user_id (), 'dismissed_wp_pointers', true ) );
60
+ $this->logger->trace ( $dismissed );
61
+ $valid_pointers = array ();
62
+
63
+ // Check pointers and remove dismissed ones.
64
+ foreach ( $pointers as $pointer_id => $pointer ) {
65
+
66
+ // Sanity check
67
+ if (in_array ( $pointer_id, $dismissed ) || empty ( $pointer ) || empty ( $pointer_id ) || empty ( $pointer ['target'] ) || empty ( $pointer ['options'] ))
68
+ continue;
69
+
70
+ $pointer ['pointer_id'] = $pointer_id;
71
+
72
+ // Add the pointer to $valid_pointers array
73
+ $valid_pointers ['pointers'] [] = $pointer;
74
+ }
75
+
76
+ // No valid pointers? Stop here.
77
+ if (empty ( $valid_pointers )) {
78
+ return;
79
+ }
80
+
81
+ // Add pointers style to queue.
82
+ wp_enqueue_style ( 'wp-pointer' );
83
+
84
+ // Add pointers script to queue. Add custom script.
85
+ /**
86
+ * @todo Check if this work
87
+ */
88
+ /*
89
+ wp_enqueue_script ( 'postman_admin_pointer', plugins_url ( 'script/postman-admin-pointer.js', $this->rootPluginFilenameAndPath ), array (
90
+ 'wp-pointer'
91
+ ) );
92
+
93
+ // Add pointer options to script.
94
+ wp_localize_script ( 'postman_admin_pointer', 'postman_admin_pointer', $valid_pointers );
95
+ */
96
+ $this->logger->trace ( 'out wptuts' );
97
+ }
98
+ }
99
+ function wptuts_register_pointer_testing($p) {
100
+ // only do this for administrators
101
+ if (PostmanUtils::isAdmin () && false) {
102
+ $p ['postman16_log'] = array (
103
+ 'target' => '.configure_manually',
104
+ 'options' => array (
105
+ 'content' => '',
106
+ 'position' => array (
107
+ 'edge' => 'top',
108
+ 'align' => 'left'
109
+ )
110
+ )
111
+ );
112
+ return $p;
113
+ }
114
+ }
115
+ }
116
+ }
Postman/Postman-Controller/PostmanDashboardWidgetController.php CHANGED
@@ -1,161 +1,161 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- if (! class_exists ( "PostmanDashboardWidgetController" )) {
7
-
8
- //
9
- class PostmanDashboardWidgetController {
10
- private $rootPluginFilenameAndPath;
11
- private $options;
12
- private $authorizationToken;
13
- private $wpMailBinder;
14
-
15
- /**
16
- * Start up
17
- */
18
- public function __construct($rootPluginFilenameAndPath, PostmanOptions $options, PostmanOAuthToken $authorizationToken, PostmanWpMailBinder $binder) {
19
- assert ( ! empty ( $rootPluginFilenameAndPath ) );
20
- assert ( ! empty ( $options ) );
21
- assert ( ! empty ( $authorizationToken ) );
22
- assert ( ! empty ( $binder ) );
23
- $this->rootPluginFilenameAndPath = $rootPluginFilenameAndPath;
24
- $this->options = $options;
25
- $this->authorizationToken = $authorizationToken;
26
- $this->wpMailBinder = $binder;
27
-
28
- add_action ( 'wp_dashboard_setup', array (
29
- $this,
30
- 'addDashboardWidget'
31
- ) );
32
-
33
- add_action ( 'wp_network_dashboard_setup', array (
34
- $this,
35
- 'addNetworkDashboardWidget'
36
- ) );
37
-
38
- // dashboard glance mod
39
- if ($this->options->isMailLoggingEnabled ()) {
40
- add_filter ( 'dashboard_glance_items', array (
41
- $this,
42
- 'customizeAtAGlanceDashboardWidget'
43
- ), 10, 1 );
44
- }
45
-
46
- // Postman API: register the human-readable plugin state
47
- add_filter ( 'print_postman_status', array (
48
- $this,
49
- 'print_postman_status'
50
- ) );
51
- }
52
-
53
- /**
54
- * Add a widget to the dashboard.
55
- *
56
- * This function is hooked into the 'wp_dashboard_setup' action below.
57
- */
58
- public function addDashboardWidget() {
59
- // only display to the widget to administrator
60
- if (PostmanUtils::isAdmin ()) {
61
- wp_add_dashboard_widget ( 'example_dashboard_widget', __ ( 'Postman SMTP', 'post-smtp' ), array (
62
- $this,
63
- 'printDashboardWidget'
64
- ) ); // Display function.
65
- }
66
- }
67
-
68
- /**
69
- * Add a widget to the network dashboard
70
- */
71
- public function addNetworkDashboardWidget() {
72
- // only display to the widget to administrator
73
- if (PostmanUtils::isAdmin ()) {
74
- wp_add_dashboard_widget ( 'example_dashboard_widget', __ ( 'Postman SMTP', 'post-smtp' ), array (
75
- $this,
76
- 'printNetworkDashboardWidget'
77
- ) ); // Display function.
78
- }
79
- }
80
-
81
- /**
82
- * Create the function to output the contents of our Dashboard Widget.
83
- */
84
- public function printDashboardWidget() {
85
- $goToSettings = sprintf ( '<a href="%s">%s</a>', PostmanUtils::getSettingsPageUrl (), __ ( 'Settings', 'post-smtp' ) );
86
- $goToEmailLog = sprintf ( '%s', _x ( 'Email Log', 'The log of Emails that have been delivered', 'post-smtp' ) );
87
- if ($this->options->isMailLoggingEnabled ()) {
88
- $goToEmailLog = sprintf ( '<a href="%s">%s</a>', PostmanUtils::getEmailLogPageUrl (), $goToEmailLog );
89
- }
90
- apply_filters ( 'print_postman_status', null );
91
- printf ( '<p>%s | %s</p>', $goToEmailLog, $goToSettings );
92
- }
93
-
94
- /**
95
- * Print the human-readable plugin state
96
- */
97
- public function print_postman_status() {
98
- if (! PostmanPreRequisitesCheck::isReady ()) {
99
- printf ( '<p><span style="color:red">%s</span></p>', __ ( 'Error: Postman is missing a required PHP library.', 'post-smtp' ) );
100
- } else if ($this->wpMailBinder->isUnboundDueToException ()) {
101
- printf ( '<p><span style="color:red">%s</span></p>', __ ( 'Postman: wp_mail has been declared by another plugin or theme, so you won\'t be able to use Postman until the conflict is resolved.', 'post-smtp' ) );
102
- } else {
103
- if ($this->options->getRunMode () != PostmanOptions::RUN_MODE_PRODUCTION) {
104
- printf ( '<p><span style="background-color:yellow">%s</span></p>', __ ( 'Postman is in <em>non-Production</em> mode and is dumping all emails.', 'post-smtp' ) );
105
- } else if (PostmanTransportRegistry::getInstance ()->getSelectedTransport ()->isConfiguredAndReady ()) {
106
- printf ( '<p class="wp-menu-image dashicons-before dashicons-email"> %s </p>', sprintf ( _n ( '<span style="color:green">Postman is configured</span> and has delivered <span style="color:green">%d</span> email.', '<span style="color:green">Postman is configured</span> and has delivered <span style="color:green">%d</span> emails.', PostmanState::getInstance ()->getSuccessfulDeliveries (), 'post-smtp' ), PostmanState::getInstance ()->getSuccessfulDeliveries () ) );
107
- } else {
108
- printf ( '<p><span style="color:red">%s</span></p>', __ ( 'Postman is <em>not</em> configured and is mimicking out-of-the-box WordPress email delivery.', 'post-smtp' ) );
109
- }
110
- $currentTransport = PostmanTransportRegistry::getInstance ()->getActiveTransport ();
111
- $deliveryDetails = $currentTransport->getDeliveryDetails ( $this->options );
112
- printf ( '<p>%s</p>', $deliveryDetails );
113
- }
114
- }
115
-
116
- /**
117
- * Create the function to output the contents of our Dashboard Widget.
118
- */
119
- public function printNetworkDashboardWidget() {
120
- printf ( '<p class="wp-menu-image dashicons-before dashicons-email"> %s</p>', __ ( 'Postman is operating in per-site mode.', 'post-smtp' ) );
121
- }
122
-
123
- /**
124
- * From http://www.hughlashbrooke.com/2014/02/wordpress-add-items-glance-widget/
125
- * http://coffeecupweb.com/how-to-add-custom-post-types-to-at-a-glance-dashboard-widget-in-wordpress/
126
- *
127
- * @param mixed $items
128
- * @return string
129
- */
130
- function customizeAtAGlanceDashboardWidget($items = array()) {
131
- // only modify the At-a-Glance for administrators
132
- if (PostmanUtils::isAdmin ()) {
133
- $post_types = array (
134
- PostmanEmailLogPostType::POSTMAN_CUSTOM_POST_TYPE_SLUG
135
- );
136
-
137
- foreach ( $post_types as $type ) {
138
-
139
- if (! post_type_exists ( $type ))
140
- continue;
141
-
142
- $num_posts = wp_count_posts ( $type );
143
-
144
- if ($num_posts) {
145
-
146
- $published = intval ( $num_posts->publish );
147
- $privated = intval ( $num_posts->private );
148
- $post_type = get_post_type_object ( $type );
149
-
150
- $text = _n ( '%s ' . $post_type->labels->singular_name, '%s ' . $post_type->labels->name, $privated, 'post-smtp' );
151
- $text = sprintf ( $text, number_format_i18n ( $privated ) );
152
-
153
- $items [] = sprintf ( '<a class="%1$s-count" href="%3$s">%2$s</a>', $type, $text, PostmanUtils::getEmailLogPageUrl () ) . "\n";
154
- }
155
- }
156
-
157
- return $items;
158
- }
159
- }
160
- }
161
  }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ if (! class_exists ( "PostmanDashboardWidgetController" )) {
7
+
8
+ //
9
+ class PostmanDashboardWidgetController {
10
+ private $rootPluginFilenameAndPath;
11
+ private $options;
12
+ private $authorizationToken;
13
+ private $wpMailBinder;
14
+
15
+ /**
16
+ * Start up
17
+ */
18
+ public function __construct($rootPluginFilenameAndPath, PostmanOptions $options, PostmanOAuthToken $authorizationToken, PostmanWpMailBinder $binder) {
19
+ assert ( ! empty ( $rootPluginFilenameAndPath ) );
20
+ assert ( ! empty ( $options ) );
21
+ assert ( ! empty ( $authorizationToken ) );
22
+ assert ( ! empty ( $binder ) );
23
+ $this->rootPluginFilenameAndPath = $rootPluginFilenameAndPath;
24
+ $this->options = $options;
25
+ $this->authorizationToken = $authorizationToken;
26
+ $this->wpMailBinder = $binder;
27
+
28
+ add_action ( 'wp_dashboard_setup', array (
29
+ $this,
30
+ 'addDashboardWidget'
31
+ ) );
32
+
33
+ add_action ( 'wp_network_dashboard_setup', array (
34
+ $this,
35
+ 'addNetworkDashboardWidget'
36
+ ) );
37
+
38
+ // dashboard glance mod
39
+ if ($this->options->isMailLoggingEnabled ()) {
40
+ add_filter ( 'dashboard_glance_items', array (
41
+ $this,
42
+ 'customizeAtAGlanceDashboardWidget'
43
+ ), 10, 1 );
44
+ }
45
+
46
+ // Postman API: register the human-readable plugin state
47
+ add_filter ( 'print_postman_status', array (
48
+ $this,
49
+ 'print_postman_status'
50
+ ) );
51
+ }
52
+
53
+ /**
54
+ * Add a widget to the dashboard.
55
+ *
56
+ * This function is hooked into the 'wp_dashboard_setup' action below.
57
+ */
58
+ public function addDashboardWidget() {
59
+ // only display to the widget to administrator
60
+ if (PostmanUtils::isAdmin ()) {
61
+ wp_add_dashboard_widget ( 'example_dashboard_widget', __ ( 'Postman SMTP', 'post-smtp' ), array (
62
+ $this,
63
+ 'printDashboardWidget'
64
+ ) ); // Display function.
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Add a widget to the network dashboard
70
+ */
71
+ public function addNetworkDashboardWidget() {
72
+ // only display to the widget to administrator
73
+ if (PostmanUtils::isAdmin ()) {
74
+ wp_add_dashboard_widget ( 'example_dashboard_widget', __ ( 'Postman SMTP', 'post-smtp' ), array (
75
+ $this,
76
+ 'printNetworkDashboardWidget'
77
+ ) ); // Display function.
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Create the function to output the contents of our Dashboard Widget.
83
+ */
84
+ public function printDashboardWidget() {
85
+ $goToSettings = sprintf ( '<a href="%s">%s</a>', PostmanUtils::getSettingsPageUrl (), __ ( 'Settings', 'post-smtp' ) );
86
+ $goToEmailLog = sprintf ( '%s', _x ( 'Email Log', 'The log of Emails that have been delivered', 'post-smtp' ) );
87
+ if ($this->options->isMailLoggingEnabled ()) {
88
+ $goToEmailLog = sprintf ( '<a href="%s">%s</a>', PostmanUtils::getEmailLogPageUrl (), $goToEmailLog );
89
+ }
90
+ apply_filters ( 'print_postman_status', null );
91
+ printf ( '<p>%s | %s</p>', $goToEmailLog, $goToSettings );
92
+ }
93
+
94
+ /**
95
+ * Print the human-readable plugin state
96
+ */
97
+ public function print_postman_status() {
98
+ if (! PostmanPreRequisitesCheck::isReady ()) {
99
+ printf ( '<p><span style="color:red">%s</span></p>', __ ( 'Error: Postman is missing a required PHP library.', 'post-smtp' ) );
100
+ } else if ($this->wpMailBinder->isUnboundDueToException ()) {
101
+ printf ( '<p><span style="color:red">%s</span></p>', __ ( 'Postman: wp_mail has been declared by another plugin or theme, so you won\'t be able to use Postman until the conflict is resolved.', 'post-smtp' ) );
102
+ } else {
103
+ if ($this->options->getRunMode () != PostmanOptions::RUN_MODE_PRODUCTION) {
104
+ printf ( '<p><span style="background-color:yellow">%s</span></p>', __ ( 'Postman is in <em>non-Production</em> mode and is dumping all emails.', 'post-smtp' ) );
105
+ } else if (PostmanTransportRegistry::getInstance ()->getSelectedTransport ()->isConfiguredAndReady ()) {
106
+ printf ( '<p class="wp-menu-image dashicons-before dashicons-email"> %s </p>', sprintf ( _n ( '<span style="color:green">Postman is configured</span> and has delivered <span style="color:green">%d</span> email.', '<span style="color:green">Postman is configured</span> and has delivered <span style="color:green">%d</span> emails.', PostmanState::getInstance ()->getSuccessfulDeliveries (), 'post-smtp' ), PostmanState::getInstance ()->getSuccessfulDeliveries () ) );
107
+ } else {
108
+ printf ( '<p><span style="color:red">%s</span></p>', __ ( 'Postman is <em>not</em> configured and is mimicking out-of-the-box WordPress email delivery.', 'post-smtp' ) );
109
+ }
110
+ $currentTransport = PostmanTransportRegistry::getInstance ()->getActiveTransport ();
111
+ $deliveryDetails = $currentTransport->getDeliveryDetails ( $this->options );
112
+ printf ( '<p>%s</p>', $deliveryDetails );
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Create the function to output the contents of our Dashboard Widget.
118
+ */
119
+ public function printNetworkDashboardWidget() {
120
+ printf ( '<p class="wp-menu-image dashicons-before dashicons-email"> %s</p>', __ ( 'Postman is operating in per-site mode.', 'post-smtp' ) );
121
+ }
122
+
123
+ /**
124
+ * From http://www.hughlashbrooke.com/2014/02/wordpress-add-items-glance-widget/
125
+ * http://coffeecupweb.com/how-to-add-custom-post-types-to-at-a-glance-dashboard-widget-in-wordpress/
126
+ *
127
+ * @param mixed $items
128
+ * @return string
129
+ */
130
+ function customizeAtAGlanceDashboardWidget($items = array()) {
131
+ // only modify the At-a-Glance for administrators
132
+ if (PostmanUtils::isAdmin ()) {
133
+ $post_types = array (
134
+ PostmanEmailLogPostType::POSTMAN_CUSTOM_POST_TYPE_SLUG
135
+ );
136
+
137
+ foreach ( $post_types as $type ) {
138
+
139
+ if (! post_type_exists ( $type ))
140
+ continue;
141
+
142
+ $num_posts = wp_count_posts ( $type );
143
+
144
+ if ($num_posts) {
145
+
146
+ $published = intval ( $num_posts->publish );
147
+ $privated = intval ( $num_posts->private );
148
+ $post_type = get_post_type_object ( $type );
149
+
150
+ $text = _n ( '%s ' . $post_type->labels->singular_name, '%s ' . $post_type->labels->name, $privated, 'post-smtp' );
151
+ $text = sprintf ( $text, number_format_i18n ( $privated ) );
152
+
153
+ $items [] = sprintf ( '<a class="%1$s-count" href="%3$s">%2$s</a>', $type, $text, PostmanUtils::getEmailLogPageUrl () ) . "\n";
154
+ }
155
+ }
156
+
157
+ return $items;
158
+ }
159
+ }
160
+ }
161
  }
Postman/Postman-Controller/PostmanManageConfigurationAjaxHandler.php CHANGED
@@ -1,68 +1,68 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- class PostmanWizardSocket {
7
-
8
- // these variables are populated by the Port Test
9
- public $hostname;
10
- public $hostnameDomainOnly;
11
- public $port;
12
- public $protocol;
13
- public $secure;
14
- public $mitm;
15
- public $reportedHostname;
16
- public $reportedHostnameDomainOnly;
17
- public $message;
18
- public $startTls;
19
- public $authPlain;
20
- public $auth_login;
21
- public $auth_crammd5;
22
- public $auth_xoauth;
23
- public $auth_none;
24
- public $try_smtps;
25
- public $success;
26
- public $transport;
27
-
28
- /**
29
- * Extra Fields
30
- *
31
- * @since 2.1
32
- */
33
- public $data = false;
34
-
35
- // these variables are populated by The Transport Recommenders
36
- public $label;
37
- public $id;
38
-
39
- /**
40
- *
41
- * @param mixed $queryHostData
42
- */
43
- function __construct($queryHostData) {
44
- $this->hostname = $queryHostData ['hostname'];
45
- $this->hostnameDomainOnly = $queryHostData ['hostname_domain_only'];
46
- $this->port = $queryHostData ['port'];
47
- $this->protocol = $queryHostData ['protocol'];
48
- $this->secure = PostmanUtils::parseBoolean ( $queryHostData ['secure'] );
49
- $this->mitm = PostmanUtils::parseBoolean ( $queryHostData ['mitm'] );
50
- $this->reportedHostname = $queryHostData ['reported_hostname'];
51
- $this->reportedHostnameDomainOnly = $queryHostData ['reported_hostname_domain_only'];
52
- $this->message = $queryHostData ['message'];
53
- $this->startTls = PostmanUtils::parseBoolean ( $queryHostData ['start_tls'] );
54
- $this->authPlain = PostmanUtils::parseBoolean ( $queryHostData ['auth_plain'] );
55
- $this->auth_login = PostmanUtils::parseBoolean ( $queryHostData ['auth_login'] );
56
- $this->auth_crammd5 = PostmanUtils::parseBoolean ( $queryHostData ['auth_crammd5'] );
57
- $this->auth_xoauth = PostmanUtils::parseBoolean ( $queryHostData ['auth_xoauth'] );
58
- $this->auth_none = PostmanUtils::parseBoolean ( $queryHostData ['auth_none'] );
59
- $this->try_smtps = PostmanUtils::parseBoolean ( $queryHostData ['try_smtps'] );
60
- $this->success = PostmanUtils::parseBoolean ( $queryHostData ['success'] );
61
- $this->transport = $queryHostData ['transport'];
62
- $this->data = $queryHostData['data'];
63
-
64
- assert ( ! empty ( $this->transport ) );
65
- $this->id = sprintf ( '%s_%s', $this->hostname, $this->port );
66
- }
67
- }
68
-
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ class PostmanWizardSocket {
7
+
8
+ // these variables are populated by the Port Test
9
+ public $hostname;
10
+ public $hostnameDomainOnly;
11
+ public $port;
12
+ public $protocol;
13
+ public $secure;
14
+ public $mitm;
15
+ public $reportedHostname;
16
+ public $reportedHostnameDomainOnly;
17
+ public $message;
18
+ public $startTls;
19
+ public $authPlain;
20
+ public $auth_login;
21
+ public $auth_crammd5;
22
+ public $auth_xoauth;
23
+ public $auth_none;
24
+ public $try_smtps;
25
+ public $success;
26
+ public $transport;
27
+
28
+ /**
29
+ * Extra Fields
30
+ *
31
+ * @since 2.1
32
+ */
33
+ public $data = false;
34
+
35
+ // these variables are populated by The Transport Recommenders
36
+ public $label;
37
+ public $id;
38
+
39
+ /**
40
+ *
41
+ * @param mixed $queryHostData
42
+ */
43
+ function __construct($queryHostData) {
44
+ $this->hostname = $queryHostData ['hostname'];
45
+ $this->hostnameDomainOnly = $queryHostData ['hostname_domain_only'];
46
+ $this->port = $queryHostData ['port'];
47
+ $this->protocol = $queryHostData ['protocol'];
48
+ $this->secure = PostmanUtils::parseBoolean ( $queryHostData ['secure'] );
49
+ $this->mitm = PostmanUtils::parseBoolean ( $queryHostData ['mitm'] );
50
+ $this->reportedHostname = $queryHostData ['reported_hostname'];
51
+ $this->reportedHostnameDomainOnly = $queryHostData ['reported_hostname_domain_only'];
52
+ $this->message = $queryHostData ['message'];
53
+ $this->startTls = PostmanUtils::parseBoolean ( $queryHostData ['start_tls'] );
54
+ $this->authPlain = PostmanUtils::parseBoolean ( $queryHostData ['auth_plain'] );
55
+ $this->auth_login = PostmanUtils::parseBoolean ( $queryHostData ['auth_login'] );
56
+ $this->auth_crammd5 = PostmanUtils::parseBoolean ( $queryHostData ['auth_crammd5'] );
57
+ $this->auth_xoauth = PostmanUtils::parseBoolean ( $queryHostData ['auth_xoauth'] );
58
+ $this->auth_none = PostmanUtils::parseBoolean ( $queryHostData ['auth_none'] );
59
+ $this->try_smtps = PostmanUtils::parseBoolean ( $queryHostData ['try_smtps'] );
60
+ $this->success = PostmanUtils::parseBoolean ( $queryHostData ['success'] );
61
+ $this->transport = $queryHostData ['transport'];
62
+ $this->data = $queryHostData['data'];
63
+
64
+ assert ( ! empty ( $this->transport ) );
65
+ $this->id = sprintf ( '%s_%s', $this->hostname, $this->port );
66
+ }
67
+ }
68
+
Postman/Postman-Controller/PostmanWelcomeController.php CHANGED
@@ -1,217 +1,217 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- class PostmanWelcomeController {
7
-
8
- private $rootPluginFilenameAndPath, $pluginUrl, $version;
9
-
10
- public function __construct( $rootPluginFilenameAndPath ) {
11
- $this->rootPluginFilenameAndPath = $rootPluginFilenameAndPath;
12
- $this->pluginUrl = plugins_url( 'style', $rootPluginFilenameAndPath );
13
- $this->version = PostmanState::getInstance()->getVersion();
14
-
15
- add_action( 'admin_menu', array( $this, 'add_menus' ) );
16
- add_action( 'admin_head', array( $this, 'admin_head' ) );
17
- }
18
-
19
- public function add_menus() {
20
-
21
- if ( current_user_can( 'manage_options' ) ) {
22
-
23
- // About
24
- add_dashboard_page(
25
- __( 'Welcome', 'post-smtp' ),
26
- __( 'Welcome', 'post-smtp' ),
27
- 'manage_options',
28
- 'post-about',
29
- array( $this, 'about_screen' )
30
- );
31
-
32
- // Credits
33
- add_dashboard_page(
34
- __( 'Credits', 'post-smtp' ),
35
- __( 'Credits', 'post-smtp' ),
36
- 'manage_options',
37
- 'post-credits',
38
- array( $this, 'credits_screen' )
39
- );
40
-
41
- // add_action( 'admin_print_styles-' . $page, array( $this, 'postman_about_enqueue_resources' ) );
42
- }
43
- }
44
-
45
- public function admin_head() {
46
- remove_submenu_page( 'index.php', 'post-about' );
47
- remove_submenu_page( 'index.php', 'post-credits' );
48
- }
49
-
50
- public function postman_about_enqueue_resources() {
51
- // wp_enqueue_style( 'font-awsome', '' );
52
- }
53
-
54
-
55
- public function about_screen() {
56
- ?>
57
- <style type="text/css">
58
- .post-badge {
59
- position: absolute;
60
- top: 0;
61
- right: 0;
62
- padding-top: 142px;
63
- height: 50px;
64
- width: 140px;
65
- color: #000;
66
- font-weight: bold;
67
- font-size: 14px;
68
- text-align: center;
69
- margin: 0 -5px;
70
- background: url( <?php echo $this->pluginUrl; ?>/images/badge.png) no-repeat;
71
- }
72
-
73
- .about-wrap [class$="-col"] {
74
- flex-wrap: nowrap !important;
75
- }
76
- </style>
77
- <div class="wrap about-wrap">
78
- <h1><?php printf( esc_html__( 'Welcome to Post SMTP %s', 'post-smtp' ), $this->version ); ?></h1>
79
- <div class="about-text"><?php printf( esc_html__( 'Thank you for updating! Post SMTP %s is bundled up and ready to take your SMTP needs to the next level!', 'post-smtp' ), $this->version ); ?><br>
80
- <?php printf( '<strong>%s</strong>','Post SMTP support every SMTP service: Gmail/G-suite, SendGrid, Mandrill, Office365, and more...' ); ?>
81
- </div>
82
- <div class="post-badge"><?php printf( esc_html__( 'Version %s', 'post-smtp' ), $this->version ); ?></div>
83
-
84
- <h2 class="nav-tab-wrapper">
85
- <a class="nav-tab nav-tab-active" href="<?php echo esc_url( admin_url( add_query_arg( array( 'page' => 'post-about' ), 'index.php' ) ) ); ?>">
86
- <?php esc_html_e( 'What&#8217;s New', 'post-smtp' ); ?>
87
- </a><a class="nav-tab" href="<?php echo esc_url( admin_url( add_query_arg( array( 'page' => 'post-credits' ), 'index.php' ) ) ); ?>">
88
- <?php esc_html_e( 'Credits', 'post-smtp' ); ?>
89
- </a>
90
- </h2>
91
-
92
- <div class="changelog">
93
- <h3><?php esc_html_e( 'Email Log', 'post-smtp' ); ?></h3>
94
-
95
- <div class="feature-section col two-col">
96
- <div class="last-feature">
97
- <h4><?php esc_html_e( 'Email log filter', 'post-smtp' ); ?></h4>
98
- <p>
99
- <?php esc_html_e( 'You can easily filter by dates and search in your log.', 'post-smtp' ); ?>
100
- <img src="<?php echo $this->pluginUrl; ?>/images/filter-preview.gif">
101
- </p>
102
- </div>
103
-
104
- <div>
105
- <h4><?php esc_html_e( 'Multiple emails resend', 'post-smtp' ); ?></h4>
106
- <p>
107
- <?php esc_html_e( 'Resend any email to the original recipient or any other emails you choose.', 'post-smtp' ); ?>
108
- <img src="<?php echo $this->pluginUrl; ?>/images/resend-preview.gif">
109
- </p>
110
- </div>
111
- </div>
112
- </div>
113
-
114
- <div class="changelog">
115
- <h3><?php esc_html_e( 'The best delivery experience', 'post-smtp' ); ?></h3>
116
-
117
- <div class="feature-section col one-col">
118
- <div class="last-feature">
119
- <p><?php esc_html_e( 'Easy-to-use, powerful Setup Wizard for perfect configuration,
120
- Commercial-grade Connectivity Tester to diagnose server issues,
121
- Log and resend all emails; see the exact cause of failed emails,
122
- Supports International alphabets, HTML Mail and MultiPart/Alternative,
123
- Supports forced recipients (cc, bcc, to) and custom email headers,
124
- SASL Support: Plain/Login/CRAM-MD5/XOAUTH2 authentication,
125
- Security Support: SMTPS and STARTTLS (SSL/TLS),
126
- Copy configuration to other instances of Post.', 'post-smtp' ); ?></p>
127
- </div>
128
- </div>
129
-
130
- <div class="feature-section col three-col">
131
- <div>
132
- <h4><?php esc_html_e( 'Email log HTML preview', 'post-smtp' ); ?></h4>
133
- <p><?php esc_html_e( 'You can now see sent emails as HTML.', 'post-smtp' ); ?></p>
134
- </div>
135
-
136
- <div>
137
- <h4><?php esc_html_e( 'Continues email delivery', 'post-smtp' ); ?></h4>
138
- <p><?php esc_html_e( 'if email fail to sent you will get notified using the local mail system.', 'post-smtp' ); ?></p>
139
- </div>
140
-
141
- <div class="last-feature">
142
- <h4><?php esc_html_e( 'The best debugging tools.', 'post-smtp' ); ?></h4>
143
- <p><?php esc_html_e( 'Full Transcripts, Connectivity Test, Diagnostic Test.', 'post-smtp' ); ?></p>
144
- </div>
145
- </div>
146
- </div>
147
-
148
- <div class="return-to-dashboard">
149
- <a href="<?php echo esc_url( admin_url( add_query_arg( array( 'page' => 'postman' ), 'admin.php' ) ) ); ?>"><?php esc_html_e( 'Go to Post SMTP Settings', 'post-smtp' ); ?></a>
150
- </div>
151
-
152
- </div>
153
-
154
- <?php
155
- }
156
-
157
- public function credits_screen() {
158
- ?>
159
- <style type="text/css">
160
- .post-badge {
161
- position: absolute;
162
- top: 0;
163
- right: 0;
164
- padding-top: 142px;
165
- height: 50px;
166
- width: 140px;
167
- color: #000;
168
- font-weight: bold;
169
- font-size: 14px;
170
- text-align: center;
171
- margin: 0 -5px;
172
- background: url( <?php echo $this->pluginUrl; ?>/images/badge.png) no-repeat;
173
- }
174
- </style>
175
- <div class="wrap about-wrap">
176
- <h1><?php printf( esc_html__( 'Welcome to Post SMTP %s', 'post-smtp' ), $this->version ); ?></h1>
177
- <div class="about-text"><?php printf( esc_html__( 'Thank you for updating! bbPress %s is waxed, polished, and ready for you to take it for a lap or two around the block!', 'post-smtp' ), $this->version ); ?></div>
178
- <div class="post-badge"><?php printf( esc_html__( 'Version %s', 'post-smtp' ), $this->version ); ?></div>
179
-
180
- <h2 class="nav-tab-wrapper">
181
- <a href="<?php echo esc_url( admin_url( add_query_arg( array( 'page' => 'post-about' ), 'index.php' ) ) ); ?>" class="nav-tab">
182
- <?php esc_html_e( 'What&#8217;s New', 'post-smtp' ); ?>
183
- </a><a href="<?php echo esc_url( admin_url( add_query_arg( array( 'page' => 'post-credits' ), 'index.php' ) ) ); ?>" class="nav-tab nav-tab-active">
184
- <?php esc_html_e( 'Credits', 'post-smtp' ); ?>
185
- </a>
186
- </h2>
187
-
188
- <p class="about-description"><?php esc_html_e( 'Post SMTP started by Jason Hendriks, Jason left the project and Yehuda Hassine (me) continue his work.', 'post-smtp' ); ?></p>
189
-
190
- <h4 class="wp-people-group"><?php esc_html_e( 'Project Leaders', 'post-smtp' ); ?></h4>
191
- <ul class="wp-people-group " id="wp-people-group-project-leaders">
192
- <li class="wp-person" id="wp-person-yehudah">
193
- <a href="http://profiles.wordpress.org/yehudah"><img src="https://secure.gravatar.com/avatar/c561638d04ea8fef351f974dbb9ece39?s=60&d=mm&r=g" class="gravatar" alt="Yehuda Hassine" /></a>
194
- <a class="web" href="http://profiles.wordpress.org/yehudah">Yehuda Hassine</a>
195
- <span class="title"><?php esc_html_e( 'Lead Developer', 'post-smtp' ); ?></span>
196
- </li>
197
- </ul>
198
-
199
- <h4 class="wp-people-group"><?php esc_html_e( 'Top Community Members', 'post-smtp' ); ?></h4>
200
- <h5><?php esc_html_e( 'Here I will list top users that help Post SMTP grow (bugs, features, etc...)', 'post-smtp' ); ?>
201
- <p class="wp-credits-list">
202
- <a href="http://profiles.wordpress.org/diegocanal">diegocanal</a>,
203
- <a href="http://profiles.wordpress.org/jyourstone">Johan Yourstone</a>,
204
- <a href="http://profiles.wordpress.org/bodhirayo">bodhirayo</a>,
205
- <a href="http://profiles.wordpress.org/buzztone">Neil Murray </a>,
206
- <a href="#">A place waiting for you? :-) </a>
207
- </p>
208
-
209
- <div class="return-to-dashboard">
210
- <a href="<?php echo esc_url( admin_url( add_query_arg( array( 'page' => 'postman' ), 'admin.php' ) ) ); ?>"><?php esc_html_e( 'Go to Post SMTP Settings', 'post-smtp' ); ?></a>
211
- </div>
212
-
213
- </div>
214
-
215
- <?php
216
- }
217
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ class PostmanWelcomeController {
7
+
8
+ private $rootPluginFilenameAndPath, $pluginUrl, $version;
9
+
10
+ public function __construct( $rootPluginFilenameAndPath ) {
11
+ $this->rootPluginFilenameAndPath = $rootPluginFilenameAndPath;
12
+ $this->pluginUrl = plugins_url( 'style', $rootPluginFilenameAndPath );
13
+ $this->version = PostmanState::getInstance()->getVersion();
14
+
15
+ add_action( 'admin_menu', array( $this, 'add_menus' ) );
16
+ add_action( 'admin_head', array( $this, 'admin_head' ) );
17
+ }
18
+
19
+ public function add_menus() {
20
+
21
+ if ( current_user_can( 'manage_options' ) ) {
22
+
23
+ // About
24
+ add_dashboard_page(
25
+ __( 'Welcome', 'post-smtp' ),
26
+ __( 'Welcome', 'post-smtp' ),
27
+ 'manage_options',
28
+ 'post-about',
29
+ array( $this, 'about_screen' )
30
+ );
31
+
32
+ // Credits
33
+ add_dashboard_page(
34
+ __( 'Credits', 'post-smtp' ),
35
+ __( 'Credits', 'post-smtp' ),
36
+ 'manage_options',
37
+ 'post-credits',
38
+ array( $this, 'credits_screen' )
39
+ );
40
+
41
+ // add_action( 'admin_print_styles-' . $page, array( $this, 'postman_about_enqueue_resources' ) );
42
+ }
43
+ }
44
+
45
+ public function admin_head() {
46
+ remove_submenu_page( 'index.php', 'post-about' );
47
+ remove_submenu_page( 'index.php', 'post-credits' );
48
+ }
49
+
50
+ public function postman_about_enqueue_resources() {
51
+ // wp_enqueue_style( 'font-awsome', '' );
52
+ }
53
+
54
+
55
+ public function about_screen() {
56
+ ?>
57
+ <style type="text/css">
58
+ .post-badge {
59
+ position: absolute;
60
+ top: 0;
61
+ right: 0;
62
+ padding-top: 142px;
63
+ height: 50px;
64
+ width: 140px;
65
+ color: #000;
66
+ font-weight: bold;
67
+ font-size: 14px;
68
+ text-align: center;
69
+ margin: 0 -5px;
70
+ background: url( <?php echo $this->pluginUrl; ?>/images/badge.png) no-repeat;
71
+ }
72
+
73
+ .about-wrap [class$="-col"] {
74
+ flex-wrap: nowrap !important;
75
+ }
76
+ </style>
77
+ <div class="wrap about-wrap">
78
+ <h1><?php printf( esc_html__( 'Welcome to Post SMTP %s', 'post-smtp' ), $this->version ); ?></h1>
79
+ <div class="about-text"><?php printf( esc_html__( 'Thank you for updating! Post SMTP %s is bundled up and ready to take your SMTP needs to the next level!', 'post-smtp' ), $this->version ); ?><br>
80
+ <?php printf( '<strong>%s</strong>','Post SMTP support every SMTP service: Gmail/G-suite, SendGrid, Mandrill, Office365, and more...' ); ?>
81
+ </div>
82
+ <div class="post-badge"><?php printf( esc_html__( 'Version %s', 'post-smtp' ), $this->version ); ?></div>
83
+
84
+ <h2 class="nav-tab-wrapper">
85
+ <a class="nav-tab nav-tab-active" href="<?php echo esc_url( admin_url( add_query_arg( array( 'page' => 'post-about' ), 'index.php' ) ) ); ?>">
86
+ <?php esc_html_e( 'What&#8217;s New', 'post-smtp' ); ?>
87
+ </a><a class="nav-tab" href="<?php echo esc_url( admin_url( add_query_arg( array( 'page' => 'post-credits' ), 'index.php' ) ) ); ?>">
88
+ <?php esc_html_e( 'Credits', 'post-smtp' ); ?>
89
+ </a>
90
+ </h2>
91
+
92
+ <div class="changelog">
93
+ <h3><?php esc_html_e( 'Email Log', 'post-smtp' ); ?></h3>
94
+
95
+ <div class="feature-section col two-col">
96
+ <div class="last-feature">
97
+ <h4><?php esc_html_e( 'Email log filter', 'post-smtp' ); ?></h4>
98
+ <p>
99
+ <?php esc_html_e( 'You can easily filter by dates and search in your log.', 'post-smtp' ); ?>
100
+ <img src="<?php echo $this->pluginUrl; ?>/images/filter-preview.gif">
101
+ </p>
102
+ </div>
103
+
104
+ <div>
105
+ <h4><?php esc_html_e( 'Multiple emails resend', 'post-smtp' ); ?></h4>
106
+ <p>
107
+ <?php esc_html_e( 'Resend any email to the original recipient or any other emails you choose.', 'post-smtp' ); ?>
108
+ <img src="<?php echo $this->pluginUrl; ?>/images/resend-preview.gif">
109
+ </p>
110
+ </div>
111
+ </div>
112
+ </div>
113
+
114
+ <div class="changelog">
115
+ <h3><?php esc_html_e( 'The best delivery experience', 'post-smtp' ); ?></h3>
116
+
117
+ <div class="feature-section col one-col">
118
+ <div class="last-feature">
119
+ <p><?php esc_html_e( 'Easy-to-use, powerful Setup Wizard for perfect configuration,
120
+ Commercial-grade Connectivity Tester to diagnose server issues,
121
+ Log and resend all emails; see the exact cause of failed emails,
122
+ Supports International alphabets, HTML Mail and MultiPart/Alternative,
123
+ Supports forced recipients (cc, bcc, to) and custom email headers,
124
+ SASL Support: Plain/Login/CRAM-MD5/XOAUTH2 authentication,
125
+ Security Support: SMTPS and STARTTLS (SSL/TLS),
126
+ Copy configuration to other instances of Post.', 'post-smtp' ); ?></p>
127
+ </div>
128
+ </div>
129
+
130
+ <div class="feature-section col three-col">
131
+ <div>
132
+ <h4><?php esc_html_e( 'Email log HTML preview', 'post-smtp' ); ?></h4>
133
+ <p><?php esc_html_e( 'You can now see sent emails as HTML.', 'post-smtp' ); ?></p>
134
+ </div>
135
+
136
+ <div>
137
+ <h4><?php esc_html_e( 'Continues email delivery', 'post-smtp' ); ?></h4>
138
+ <p><?php esc_html_e( 'if email fail to sent you will get notified using the local mail system.', 'post-smtp' ); ?></p>
139
+ </div>
140
+
141
+ <div class="last-feature">
142
+ <h4><?php esc_html_e( 'The best debugging tools.', 'post-smtp' ); ?></h4>
143
+ <p><?php esc_html_e( 'Full Transcripts, Connectivity Test, Diagnostic Test.', 'post-smtp' ); ?></p>
144
+ </div>
145
+ </div>
146
+ </div>
147
+
148
+ <div class="return-to-dashboard">
149
+ <a href="<?php echo esc_url( admin_url( add_query_arg( array( 'page' => 'postman' ), 'admin.php' ) ) ); ?>"><?php esc_html_e( 'Go to Post SMTP Settings', 'post-smtp' ); ?></a>
150
+ </div>
151
+
152
+ </div>
153
+
154
+ <?php
155
+ }
156
+
157
+ public function credits_screen() {
158
+ ?>
159
+ <style type="text/css">
160
+ .post-badge {
161
+ position: absolute;
162
+ top: 0;
163
+ right: 0;
164
+ padding-top: 142px;
165
+ height: 50px;
166
+ width: 140px;
167
+ color: #000;
168
+ font-weight: bold;
169
+ font-size: 14px;
170
+ text-align: center;
171
+ margin: 0 -5px;
172
+ background: url( <?php echo $this->pluginUrl; ?>/images/badge.png) no-repeat;
173
+ }
174
+ </style>
175
+ <div class="wrap about-wrap">
176
+ <h1><?php printf( esc_html__( 'Welcome to Post SMTP %s', 'post-smtp' ), $this->version ); ?></h1>
177
+ <div class="about-text"><?php printf( esc_html__( 'Thank you for updating! bbPress %s is waxed, polished, and ready for you to take it for a lap or two around the block!', 'post-smtp' ), $this->version ); ?></div>
178
+ <div class="post-badge"><?php printf( esc_html__( 'Version %s', 'post-smtp' ), $this->version ); ?></div>
179
+
180
+ <h2 class="nav-tab-wrapper">
181
+ <a href="<?php echo esc_url( admin_url( add_query_arg( array( 'page' => 'post-about' ), 'index.php' ) ) ); ?>" class="nav-tab">
182
+ <?php esc_html_e( 'What&#8217;s New', 'post-smtp' ); ?>
183
+ </a><a href="<?php echo esc_url( admin_url( add_query_arg( array( 'page' => 'post-credits' ), 'index.php' ) ) ); ?>" class="nav-tab nav-tab-active">
184
+ <?php esc_html_e( 'Credits', 'post-smtp' ); ?>
185
+ </a>
186
+ </h2>
187
+
188
+ <p class="about-description"><?php esc_html_e( 'Post SMTP started by Jason Hendriks, Jason left the project and Yehuda Hassine (me) continue his work.', 'post-smtp' ); ?></p>
189
+
190
+ <h4 class="wp-people-group"><?php esc_html_e( 'Project Leaders', 'post-smtp' ); ?></h4>
191
+ <ul class="wp-people-group " id="wp-people-group-project-leaders">
192
+ <li class="wp-person" id="wp-person-yehudah">
193
+ <a href="http://profiles.wordpress.org/yehudah"><img src="https://secure.gravatar.com/avatar/c561638d04ea8fef351f974dbb9ece39?s=60&d=mm&r=g" class="gravatar" alt="Yehuda Hassine" /></a>
194
+ <a class="web" href="http://profiles.wordpress.org/yehudah">Yehuda Hassine</a>
195
+ <span class="title"><?php esc_html_e( 'Lead Developer', 'post-smtp' ); ?></span>
196
+ </li>
197
+ </ul>
198
+
199
+ <h4 class="wp-people-group"><?php esc_html_e( 'Top Community Members', 'post-smtp' ); ?></h4>
200
+ <h5><?php esc_html_e( 'Here I will list top users that help Post SMTP grow (bugs, features, etc...)', 'post-smtp' ); ?>
201
+ <p class="wp-credits-list">
202
+ <a href="http://profiles.wordpress.org/diegocanal">diegocanal</a>,
203
+ <a href="http://profiles.wordpress.org/jyourstone">Johan Yourstone</a>,
204
+ <a href="http://profiles.wordpress.org/bodhirayo">bodhirayo</a>,
205
+ <a href="http://profiles.wordpress.org/buzztone">Neil Murray </a>,
206
+ <a href="#">A place waiting for you? :-) </a>
207
+ </p>
208
+
209
+ <div class="return-to-dashboard">
210
+ <a href="<?php echo esc_url( admin_url( add_query_arg( array( 'page' => 'postman' ), 'admin.php' ) ) ); ?>"><?php esc_html_e( 'Go to Post SMTP Settings', 'post-smtp' ); ?></a>
211
+ </div>
212
+
213
+ </div>
214
+
215
+ <?php
216
+ }
217
+ }
Postman/Postman-Diagnostic-Test/PostmanDiagnosticTestController.php CHANGED
@@ -1,300 +1,300 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
- class PostmanDiagnosticTestController {
6
- const DIAGNOSTICS_SLUG = 'postman/diagnostics';
7
-
8
- // logging
9
- private $logger;
10
- private $options;
11
-
12
- // Holds the values to be used in the fields callbacks
13
- private $rootPluginFilenameAndPath;
14
-
15
- /**
16
- * Constructor
17
- *
18
- * @param mixed $rootPluginFilenameAndPath
19
- */
20
- public function __construct( $rootPluginFilenameAndPath ) {
21
- assert( ! empty( $rootPluginFilenameAndPath ) );
22
- assert( PostmanUtils::isAdmin() );
23
- assert( is_admin() );
24
-
25
- $this->logger = new PostmanLogger( get_class( $this ) );
26
- $this->rootPluginFilenameAndPath = $rootPluginFilenameAndPath;
27
- $this->options = PostmanOptions::getInstance();
28
-
29
- // register the admin menu
30
- PostmanUtils::registerAdminMenu( $this, 'addDiagnosticsSubmenu' );
31
-
32
- // hook on the init event
33
- add_action( 'init', array(
34
- $this,
35
- 'on_init',
36
- ) );
37
-
38
- // initialize the scripts, stylesheets and form fields
39
- add_action( 'admin_init', array(
40
- $this,
41
- 'on_admin_init',
42
- ) );
43
- }
44
-
45
- /**
46
- * Functions to execute on the init event
47
- *
48
- * "Typically used by plugins to initialize. The current user is already authenticated by this time."
49
- * ref: http://codex.wordpress.org/Plugin_API/Action_Reference#Actions_Run_During_a_Typical_Request
50
- */
51
- public function on_init() {
52
- // register Ajax handlers
53
- new PostmanGetDiagnosticsViaAjax();
54
- }
55
-
56
- /**
57
- * Fires on the admin_init method
58
- */
59
- public function on_admin_init() {
60
- $this->registerStylesAndScripts();
61
- }
62
-
63
- /**
64
- * Register and add settings
65
- */
66
- private function registerStylesAndScripts() {
67
- if ( $this->logger->isTrace() ) {
68
- $this->logger->trace( 'registerStylesAndScripts()' );
69
- }
70
-
71
- // register the javascript resource
72
- $pluginData = apply_filters( 'postman_get_plugin_metadata', null );
73
- wp_register_script( 'postman_diagnostics_script', plugins_url( 'Postman/Postman-Diagnostic-Test/postman_diagnostics.js', $this->rootPluginFilenameAndPath ), array(
74
- PostmanViewController::JQUERY_SCRIPT,
75
- PostmanViewController::POSTMAN_SCRIPT,
76
- ), $pluginData ['version'] );
77
- }
78
-
79
- /**
80
- * Register the Diagnostics screen
81
- */
82
- public function addDiagnosticsSubmenu() {
83
- $page = add_submenu_page( null, sprintf( __( '%s Setup', 'post-smtp' ), __( 'Postman SMTP', 'post-smtp' ) ), __( 'Postman SMTP', 'post-smtp' ), Postman::MANAGE_POSTMAN_CAPABILITY_NAME, PostmanDiagnosticTestController::DIAGNOSTICS_SLUG, array(
84
- $this,
85
- 'outputDiagnosticsContent',
86
- ) );
87
- // When the plugin options page is loaded, also load the stylesheet
88
- add_action( 'admin_print_styles-' . $page, array(
89
- $this,
90
- 'enqueueDiagnosticsScreenStylesheet',
91
- ) );
92
- }
93
- function enqueueDiagnosticsScreenStylesheet() {
94
- wp_enqueue_style( PostmanViewController::POSTMAN_STYLE );
95
- wp_enqueue_script( 'postman_diagnostics_script' );
96
- }
97
-
98
- /**
99
- */
100
- public function outputDiagnosticsContent() {
101
- // test features
102
- print '<div class="wrap">';
103
-
104
- PostmanViewController::outputChildPageHeader( __( 'Diagnostic Test', 'post-smtp' ) );
105
-
106
- ?>
107
- <form>
108
- <?php wp_nonce_field('post-smtp', 'security' ); ?>
109
- </form>
110
- <?php
111
-
112
- printf( '<h4>%s</h4>', __( 'Are you having issues with Postman?', 'post-smtp' ) );
113
- /* translators: where %1$s and %2$s are the URLs to the Troubleshooting and Support Forums on WordPress.org */
114
- printf( '<p style="margin:0 10px">%s</p>', sprintf( __( 'Please check the <a href="%1$s">troubleshooting and error messages</a> page and the <a href="%2$s">support forum</a>.', 'post-smtp' ), 'https://wordpress.org/plugins/post-smtp/other_notes/', 'https://wordpress.org/support/plugin/post-smtp' ) );
115
- printf( '<h4>%s</h4>', __( 'Diagnostic Test', 'post-smtp' ) );
116
- printf( '<p style="margin:0 10px">%s</p><br/>', sprintf( __( 'If you write for help, please include the following:', 'post-smtp' ), 'https://wordpress.org/plugins/post-smtp/other_notes/', 'https://wordpress.org/support/plugin/post-smtp' ) );
117
- printf( '<textarea readonly="readonly" id="diagnostic-text" cols="80" rows="15">%s</textarea>', _x( 'Checking..', 'The "please wait" message', 'post-smtp' ) );
118
- print '</div>';
119
- }
120
- }
121
-
122
- /**
123
- *
124
- * @author jasonhendriks
125
- */
126
- class PostmanGetDiagnosticsViaAjax {
127
- private $diagnostics;
128
- private $options;
129
- private $authorizationToken;
130
- /**
131
- * Constructor
132
- *
133
- * @param PostmanOptions $options
134
- */
135
- function __construct() {
136
- $this->options = PostmanOptions::getInstance();
137
- $this->authorizationToken = PostmanOAuthToken::getInstance();
138
- $this->diagnostics = '';
139
- PostmanUtils::registerAjaxHandler( 'postman_diagnostics', $this, 'getDiagnostics' );
140
- }
141
- private function addToDiagnostics( $header, $data ) {
142
- if ( isset( $data ) ) {
143
- $this->diagnostics .= sprintf( '%s: %s%s', $header, $data, PHP_EOL );
144
- }
145
- }
146
- private function getActivePlugins() {
147
- // from http://stackoverflow.com/questions/20488264/how-do-i-get-activated-plugin-list-in-wordpress-plugin-development
148
- $apl = get_option( 'active_plugins' );
149
- $plugins = get_plugins();
150
- $pluginText = array();
151
- foreach ( $apl as $p ) {
152
- if ( isset( $plugins [ $p ] ) ) {
153
- array_push( $pluginText, $plugins [ $p ] ['Name'] );
154
- }
155
- }
156
- return implode( ', ', $pluginText );
157
- }
158
- private function getPhpDependencies() {
159
- $apl = PostmanPreRequisitesCheck::getState();
160
- $pluginText = array();
161
- foreach ( $apl as $p ) {
162
- array_push( $pluginText, $p ['name'] . '=' . ($p ['ready'] ? 'Yes' : 'No') );
163
- }
164
- return implode( ', ', $pluginText );
165
- }
166
- private function getTransports() {
167
- $transports = '';
168
- foreach ( PostmanTransportRegistry::getInstance()->getTransports() as $transport ) {
169
- $transports .= ' : ' . $transport->getName();
170
- }
171
- return $transports;
172
- }
173
-
174
- /**
175
- * Diagnostic Data test to current SMTP server
176
- *
177
- * @return string
178
- */
179
- private function testConnectivity( PostmanModuleTransport $transport ) {
180
- $hostname = $transport->getHostname( $this->options );
181
- $port = $transport->getPort( $this->options );
182
- if ( ! empty( $hostname ) && ! empty( $port ) ) {
183
- $portTest = new PostmanPortTest( $transport->getHostname( $this->options ), $transport->getPort( $this->options ) );
184
- $result = $portTest->genericConnectionTest( $this->options->getConnectionTimeout() );
185
- if ( $result ) {
186
- return 'Yes';
187
- } else {
188
- return 'No';
189
- }
190
- }
191
- return 'n/a';
192
- }
193
-
194
- /**
195
- * Inspects the $wp_filter variable and returns the plugins attached to it
196
- * From: http://stackoverflow.com/questions/5224209/wordpress-how-do-i-get-all-the-registered-functions-for-the-content-filter
197
- */
198
- private function getFilters( $hook = '' ) {
199
- global $wp_filter;
200
- if ( empty( $hook ) || ! isset( $wp_filter [ $hook ] ) ) {
201
- return null; }
202
- $functionArray = array();
203
- foreach ( $wp_filter [ $hook ] as $functions ) {
204
- foreach ( $functions as $function ) {
205
- $thing = $function ['function'];
206
- if ( is_array( $thing ) ) {
207
- $name = get_class($thing [0]) . '->' . $thing [1];
208
- array_push($functionArray, $name);
209
- } elseif ( is_object( $thing ) ) {
210
- array_push( $functionArray, 'Anonymous Function' );
211
- } else {
212
- array_push( $functionArray, $thing );
213
- }
214
- }
215
- }
216
-
217
- return implode( ', ', $functionArray );
218
- }
219
-
220
- /**
221
- */
222
- public function getDiagnostics() {
223
-
224
- check_admin_referer('post-smtp', 'security');
225
-
226
- if( !current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_NAME ) ) {
227
- wp_send_json_error(
228
- array(
229
- 'Message' => 'Unauthorized.'
230
- ),
231
- 401
232
- );
233
- }
234
-
235
- $curl = curl_version();
236
- $transportRegistry = PostmanTransportRegistry::getInstance();
237
- $this->addToDiagnostics( 'Mailer', PostmanOptions::getInstance()->getSmtpMailer() );
238
- $this->addToDiagnostics( 'HostName', PostmanUtils::getServerName() );
239
- $this->addToDiagnostics( 'cURL Version', $curl['version'] );
240
- $this->addToDiagnostics( 'OpenSSL Version', $curl['ssl_version'] );
241
- $this->addToDiagnostics( 'OS', php_uname() );
242
- $this->addToDiagnostics( 'PHP', PHP_OS . ' ' . PHP_VERSION . ' ' . setlocale( LC_CTYPE, 0 ) );
243
- $this->addToDiagnostics( 'PHP Dependencies', $this->getPhpDependencies() );
244
- $this->addToDiagnostics( 'WordPress', (is_multisite() ? 'Multisite ' : '') . get_bloginfo( 'version' ) . ' ' . get_locale() . ' ' . get_bloginfo( 'charset', 'display' ) );
245
- $this->addToDiagnostics( 'WordPress Theme', wp_get_theme() );
246
- $this->addToDiagnostics( 'WordPress Plugins', $this->getActivePlugins() );
247
-
248
- $bindResult = apply_filters( 'postman_wp_mail_bind_status', null );
249
- $wp_mail_file_name = 'n/a';
250
- if ( class_exists( 'ReflectionFunction' ) ) {
251
- $wp_mail = new ReflectionFunction( 'wp_mail' );
252
- $wp_mail_file_name = realpath( $wp_mail->getFileName() );
253
- }
254
-
255
- $this->addToDiagnostics( 'WordPress wp_mail Owner', $wp_mail_file_name );
256
- $this->addToDiagnostics( 'WordPress wp_mail Filter(s)', $this->getFilters( 'wp_mail' ) );
257
- $this->addToDiagnostics( 'WordPress wp_mail_from Filter(s)', $this->getFilters( 'wp_mail_from' ) );
258
- $this->addToDiagnostics( 'WordPress wp_mail_from_name Filter(s)', $this->getFilters( 'wp_mail_from_name' ) );
259
- $this->addToDiagnostics( 'WordPress wp_mail_content_type Filter(s)', $this->getFilters( 'wp_mail_content_type' ) );
260
- $this->addToDiagnostics( 'WordPress wp_mail_charset Filter(s)', $this->getFilters( 'wp_mail_charset' ) );
261
- $this->addToDiagnostics( 'WordPress phpmailer_init Action(s)', $this->getFilters( 'phpmailer_init' ) );
262
- $pluginData = apply_filters( 'postman_get_plugin_metadata', null );
263
- $this->addToDiagnostics( 'Postman', $pluginData ['version'] );
264
- {
265
- $s1 = $this->options->getEnvelopeSender();
266
- $s2 = $this->options->getMessageSenderEmail();
267
- if ( ! empty( $s1 ) || ! empty( $s2 ) ) {
268
- $this->addToDiagnostics( 'Postman Sender Domain (Envelope|Message)', ($hostname = substr( strrchr( $this->options->getEnvelopeSender(), '@' ), 1 )) . ' | ' . ($hostname = substr( strrchr( $this->options->getMessageSenderEmail(), '@' ), 1 )) );
269
- }
270
- }
271
- $this->addToDiagnostics( 'Postman Prevent Message Sender Override (Email|Name)', ($this->options->isSenderEmailOverridePrevented() ? 'Yes' : 'No') . ' | ' . ($this->options->isSenderNameOverridePrevented() ? 'Yes' : 'No') );
272
- {
273
- // status of the active transport
274
- $transport = $transportRegistry->getActiveTransport();
275
- $this->addToDiagnostics( 'Postman Active Transport', sprintf( '%s (%s)', $transport->getName(), $transportRegistry->getPublicTransportUri( $transport ) ) );
276
- $this->addToDiagnostics( 'Postman Active Transport Status (Ready|Connected)', ($transport->isConfiguredAndReady() ? 'Yes' : 'No') . ' | ' . ($this->testConnectivity( $transport )) );
277
- }
278
- if ( $transportRegistry->getActiveTransport() != $transportRegistry->getSelectedTransport() && $transportRegistry->getSelectedTransport() != null ) {
279
- // status of the selected transport
280
- $transport = $transportRegistry->getSelectedTransport();
281
- $this->addToDiagnostics( 'Postman Selected Transport', sprintf( '%s (%s)', $transport->getName(), $transportRegistry->getPublicTransportUri( $transport ) ) );
282
- $this->addToDiagnostics( 'Postman Selected Transport Status (Ready|Connected)', ($transport->isConfiguredAndReady() ? 'Yes' : 'No') . ' | ' . ($this->testConnectivity( $transport )) );
283
- }
284
- $this->addToDiagnostics( 'Postman Deliveries (Success|Fail)', (PostmanState::getInstance()->getSuccessfulDeliveries()) . ' | ' . (PostmanState::getInstance()->getFailedDeliveries()) );
285
- if ( $this->options->getConnectionTimeout() != PostmanOptions::DEFAULT_TCP_CONNECTION_TIMEOUT || $this->options->getReadTimeout() != PostmanOptions::DEFAULT_TCP_READ_TIMEOUT ) {
286
- $this->addToDiagnostics( 'Postman TCP Timeout (Connection|Read)', $this->options->getConnectionTimeout() . ' | ' . $this->options->getReadTimeout() );
287
- }
288
- if ( $this->options->isMailLoggingEnabled() != PostmanOptions::DEFAULT_MAIL_LOG_ENABLED || $this->options->getMailLoggingMaxEntries() != PostmanOptions::DEFAULT_MAIL_LOG_ENTRIES || $this->options->getTranscriptSize() != PostmanOptions::DEFAULT_TRANSCRIPT_SIZE ) {
289
- $this->addToDiagnostics( 'Postman Email Log (Enabled|Limit|Transcript Size)', ($this->options->isMailLoggingEnabled() ? 'Yes' : 'No') . ' | ' . $this->options->getMailLoggingMaxEntries() . ' | ' . $this->options->getTranscriptSize() );
290
- }
291
- $this->addToDiagnostics( 'Postman Run Mode', $this->options->getRunMode() == PostmanOptions::RUN_MODE_PRODUCTION ? null : $this->options->getRunMode() );
292
- $this->addToDiagnostics( 'Postman PHP LogLevel', $this->options->getLogLevel() == PostmanLogger::ERROR_INT ? null : $this->options->getLogLevel() );
293
- $this->addToDiagnostics( 'Postman Stealth Mode', $this->options->isStealthModeEnabled() ? 'Yes' : null );
294
- $this->addToDiagnostics( 'Postman File Locking (Enabled|Temp Dir)', PostmanState::getInstance()->isFileLockingEnabled() ? null : 'No' . ' | ' . $this->options->getTempDirectory() );
295
- $response = array(
296
- 'message' => $this->diagnostics,
297
- );
298
- wp_send_json_success( $response );
299
- }
300
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+ class PostmanDiagnosticTestController {
6
+ const DIAGNOSTICS_SLUG = 'postman/diagnostics';
7
+
8
+ // logging
9
+ private $logger;
10
+ private $options;
11
+
12
+ // Holds the values to be used in the fields callbacks
13
+ private $rootPluginFilenameAndPath;
14
+
15
+ /**
16
+ * Constructor
17
+ *
18
+ * @param mixed $rootPluginFilenameAndPath
19
+ */
20
+ public function __construct( $rootPluginFilenameAndPath ) {
21
+ assert( ! empty( $rootPluginFilenameAndPath ) );
22
+ assert( PostmanUtils::isAdmin() );
23
+ assert( is_admin() );
24
+
25
+ $this->logger = new PostmanLogger( get_class( $this ) );
26
+ $this->rootPluginFilenameAndPath = $rootPluginFilenameAndPath;
27
+ $this->options = PostmanOptions::getInstance();
28
+
29
+ // register the admin menu
30
+ PostmanUtils::registerAdminMenu( $this, 'addDiagnosticsSubmenu' );
31
+
32
+ // hook on the init event
33
+ add_action( 'init', array(
34
+ $this,
35
+ 'on_init',
36
+ ) );
37
+
38
+ // initialize the scripts, stylesheets and form fields
39
+ add_action( 'admin_init', array(
40
+ $this,
41
+ 'on_admin_init',
42
+ ) );
43
+ }
44
+
45
+ /**
46
+ * Functions to execute on the init event
47
+ *
48
+ * "Typically used by plugins to initialize. The current user is already authenticated by this time."
49
+ * ref: http://codex.wordpress.org/Plugin_API/Action_Reference#Actions_Run_During_a_Typical_Request
50
+ */
51
+ public function on_init() {
52
+ // register Ajax handlers
53
+ new PostmanGetDiagnosticsViaAjax();
54
+ }
55
+
56
+ /**
57
+ * Fires on the admin_init method
58
+ */
59
+ public function on_admin_init() {
60
+ $this->registerStylesAndScripts();
61
+ }
62
+
63
+ /**
64
+ * Register and add settings
65
+ */
66
+ private function registerStylesAndScripts() {
67
+ if ( $this->logger->isTrace() ) {
68
+ $this->logger->trace( 'registerStylesAndScripts()' );
69
+ }
70
+
71
+ // register the javascript resource
72
+ $pluginData = apply_filters( 'postman_get_plugin_metadata', null );
73
+ wp_register_script( 'postman_diagnostics_script', plugins_url( 'Postman/Postman-Diagnostic-Test/postman_diagnostics.js', $this->rootPluginFilenameAndPath ), array(
74
+ PostmanViewController::JQUERY_SCRIPT,
75
+ PostmanViewController::POSTMAN_SCRIPT,
76
+ ), $pluginData ['version'] );
77
+ }
78
+
79
+ /**
80
+ * Register the Diagnostics screen
81
+ */
82
+ public function addDiagnosticsSubmenu() {
83
+ $page = add_submenu_page( null, sprintf( __( '%s Setup', 'post-smtp' ), __( 'Postman SMTP', 'post-smtp' ) ), __( 'Postman SMTP', 'post-smtp' ), Postman::MANAGE_POSTMAN_CAPABILITY_NAME, PostmanDiagnosticTestController::DIAGNOSTICS_SLUG, array(
84
+ $this,
85
+ 'outputDiagnosticsContent',
86
+ ) );
87
+ // When the plugin options page is loaded, also load the stylesheet
88
+ add_action( 'admin_print_styles-' . $page, array(
89
+ $this,
90
+ 'enqueueDiagnosticsScreenStylesheet',
91
+ ) );
92
+ }
93
+ function enqueueDiagnosticsScreenStylesheet() {
94
+ wp_enqueue_style( PostmanViewController::POSTMAN_STYLE );
95
+ wp_enqueue_script( 'postman_diagnostics_script' );
96
+ }
97
+
98
+ /**
99
+ */
100
+ public function outputDiagnosticsContent() {
101
+ // test features
102
+ print '<div class="wrap">';
103
+
104
+ PostmanViewController::outputChildPageHeader( __( 'Diagnostic Test', 'post-smtp' ) );
105
+
106
+ ?>
107
+ <form>
108
+ <?php wp_nonce_field('post-smtp', 'security' ); ?>
109
+ </form>
110
+ <?php
111
+
112
+ printf( '<h4>%s</h4>', __( 'Are you having issues with Postman?', 'post-smtp' ) );
113
+ /* translators: where %1$s and %2$s are the URLs to the Troubleshooting and Support Forums on WordPress.org */
114
+ printf( '<p style="margin:0 10px">%s</p>', sprintf( __( 'Please check the <a href="%1$s">troubleshooting and error messages</a> page and the <a href="%2$s">support forum</a>.', 'post-smtp' ), 'https://wordpress.org/plugins/post-smtp/other_notes/', 'https://wordpress.org/support/plugin/post-smtp' ) );
115
+ printf( '<h4>%s</h4>', __( 'Diagnostic Test', 'post-smtp' ) );
116
+ printf( '<p style="margin:0 10px">%s</p><br/>', sprintf( __( 'If you write for help, please include the following:', 'post-smtp' ), 'https://wordpress.org/plugins/post-smtp/other_notes/', 'https://wordpress.org/support/plugin/post-smtp' ) );
117
+ printf( '<textarea readonly="readonly" id="diagnostic-text" cols="80" rows="15">%s</textarea>', _x( 'Checking..', 'The "please wait" message', 'post-smtp' ) );
118
+ print '</div>';
119
+ }
120
+ }
121
+
122
+ /**
123
+ *
124
+ * @author jasonhendriks
125
+ */
126
+ class PostmanGetDiagnosticsViaAjax {
127
+ private $diagnostics;
128
+ private $options;
129
+ private $authorizationToken;
130
+ /**
131
+ * Constructor
132
+ *
133
+ * @param PostmanOptions $options
134
+ */
135
+ function __construct() {
136
+ $this->options = PostmanOptions::getInstance();
137
+ $this->authorizationToken = PostmanOAuthToken::getInstance();
138
+ $this->diagnostics = '';
139
+ PostmanUtils::registerAjaxHandler( 'postman_diagnostics', $this, 'getDiagnostics' );
140
+ }
141
+ private function addToDiagnostics( $header, $data ) {
142
+ if ( isset( $data ) ) {
143
+ $this->diagnostics .= sprintf( '%s: %s%s', $header, $data, PHP_EOL );
144
+ }
145
+ }
146
+ private function getActivePlugins() {
147
+ // from http://stackoverflow.com/questions/20488264/how-do-i-get-activated-plugin-list-in-wordpress-plugin-development
148
+ $apl = get_option( 'active_plugins' );
149
+ $plugins = get_plugins();
150
+ $pluginText = array();
151
+ foreach ( $apl as $p ) {
152
+ if ( isset( $plugins [ $p ] ) ) {
153
+ array_push( $pluginText, $plugins [ $p ] ['Name'] );
154
+ }
155
+ }
156
+ return implode( ', ', $pluginText );
157
+ }
158
+ private function getPhpDependencies() {
159
+ $apl = PostmanPreRequisitesCheck::getState();
160
+ $pluginText = array();
161
+ foreach ( $apl as $p ) {
162
+ array_push( $pluginText, $p ['name'] . '=' . ($p ['ready'] ? 'Yes' : 'No') );
163
+ }
164
+ return implode( ', ', $pluginText );
165
+ }
166
+ private function getTransports() {
167
+ $transports = '';
168
+ foreach ( PostmanTransportRegistry::getInstance()->getTransports() as $transport ) {
169
+ $transports .= ' : ' . $transport->getName();
170
+ }
171
+ return $transports;
172
+ }
173
+
174
+ /**
175
+ * Diagnostic Data test to current SMTP server
176
+ *
177
+ * @return string
178
+ */
179
+ private function testConnectivity( PostmanModuleTransport $transport ) {
180
+ $hostname = $transport->getHostname( $this->options );
181
+ $port = $transport->getPort( $this->options );
182
+ if ( ! empty( $hostname ) && ! empty( $port ) ) {
183
+ $portTest = new PostmanPortTest( $transport->getHostname( $this->options ), $transport->getPort( $this->options ) );
184
+ $result = $portTest->genericConnectionTest( $this->options->getConnectionTimeout() );
185
+ if ( $result ) {
186
+ return 'Yes';
187
+ } else {
188
+ return 'No';
189
+ }
190
+ }
191
+ return 'n/a';
192
+ }
193
+
194
+ /**
195
+ * Inspects the $wp_filter variable and returns the plugins attached to it
196
+ * From: http://stackoverflow.com/questions/5224209/wordpress-how-do-i-get-all-the-registered-functions-for-the-content-filter
197
+ */
198
+ private function getFilters( $hook = '' ) {
199
+ global $wp_filter;
200
+ if ( empty( $hook ) || ! isset( $wp_filter [ $hook ] ) ) {
201
+ return null; }
202
+ $functionArray = array();
203
+ foreach ( $wp_filter [ $hook ] as $functions ) {
204
+ foreach ( $functions as $function ) {
205
+ $thing = $function ['function'];
206
+ if ( is_array( $thing ) ) {
207
+ $name = get_class($thing [0]) . '->' . $thing [1];
208
+ array_push($functionArray, $name);
209
+ } elseif ( is_object( $thing ) ) {
210
+ array_push( $functionArray, 'Anonymous Function' );
211
+ } else {
212
+ array_push( $functionArray, $thing );
213
+ }
214
+ }
215
+ }
216
+
217
+ return implode( ', ', $functionArray );
218
+ }
219
+
220
+ /**
221
+ */
222
+ public function getDiagnostics() {
223
+
224
+ check_admin_referer('post-smtp', 'security');
225
+
226
+ if( !current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_NAME ) ) {
227
+ wp_send_json_error(
228
+ array(
229
+ 'Message' => 'Unauthorized.'
230
+ ),
231
+ 401
232
+ );
233
+ }
234
+
235
+ $curl = curl_version();
236
+ $transportRegistry = PostmanTransportRegistry::getInstance();
237
+ $this->addToDiagnostics( 'Mailer', PostmanOptions::getInstance()->getSmtpMailer() );
238
+ $this->addToDiagnostics( 'HostName', PostmanUtils::getServerName() );
239
+ $this->addToDiagnostics( 'cURL Version', $curl['version'] );
240
+ $this->addToDiagnostics( 'OpenSSL Version', $curl['ssl_version'] );
241
+ $this->addToDiagnostics( 'OS', php_uname() );
242
+ $this->addToDiagnostics( 'PHP', PHP_OS . ' ' . PHP_VERSION . ' ' . setlocale( LC_CTYPE, 0 ) );
243
+ $this->addToDiagnostics( 'PHP Dependencies', $this->getPhpDependencies() );
244
+ $this->addToDiagnostics( 'WordPress', (is_multisite() ? 'Multisite ' : '') . get_bloginfo( 'version' ) . ' ' . get_locale() . ' ' . get_bloginfo( 'charset', 'display' ) );
245
+ $this->addToDiagnostics( 'WordPress Theme', wp_get_theme() );
246
+ $this->addToDiagnostics( 'WordPress Plugins', $this->getActivePlugins() );
247
+
248
+ $bindResult = apply_filters( 'postman_wp_mail_bind_status', null );
249
+ $wp_mail_file_name = 'n/a';
250
+ if ( class_exists( 'ReflectionFunction' ) ) {
251
+ $wp_mail = new ReflectionFunction( 'wp_mail' );
252
+ $wp_mail_file_name = realpath( $wp_mail->getFileName() );
253
+ }
254
+
255
+ $this->addToDiagnostics( 'WordPress wp_mail Owner', $wp_mail_file_name );
256
+ $this->addToDiagnostics( 'WordPress wp_mail Filter(s)', $this->getFilters( 'wp_mail' ) );
257
+ $this->addToDiagnostics( 'WordPress wp_mail_from Filter(s)', $this->getFilters( 'wp_mail_from' ) );
258
+ $this->addToDiagnostics( 'WordPress wp_mail_from_name Filter(s)', $this->getFilters( 'wp_mail_from_name' ) );
259
+ $this->addToDiagnostics( 'WordPress wp_mail_content_type Filter(s)', $this->getFilters( 'wp_mail_content_type' ) );
260
+ $this->addToDiagnostics( 'WordPress wp_mail_charset Filter(s)', $this->getFilters( 'wp_mail_charset' ) );
261
+ $this->addToDiagnostics( 'WordPress phpmailer_init Action(s)', $this->getFilters( 'phpmailer_init' ) );
262
+ $pluginData = apply_filters( 'postman_get_plugin_metadata', null );
263
+ $this->addToDiagnostics( 'Postman', $pluginData ['version'] );
264
+ {
265
+ $s1 = $this->options->getEnvelopeSender();
266
+ $s2 = $this->options->getMessageSenderEmail();
267
+ if ( ! empty( $s1 ) || ! empty( $s2 ) ) {
268
+ $this->addToDiagnostics( 'Postman Sender Domain (Envelope|Message)', ($hostname = substr( strrchr( $this->options->getEnvelopeSender(), '@' ), 1 )) . ' | ' . ($hostname = substr( strrchr( $this->options->getMessageSenderEmail(), '@' ), 1 )) );
269
+ }
270
+ }
271
+ $this->addToDiagnostics( 'Postman Prevent Message Sender Override (Email|Name)', ($this->options->isSenderEmailOverridePrevented() ? 'Yes' : 'No') . ' | ' . ($this->options->isSenderNameOverridePrevented() ? 'Yes' : 'No') );
272
+ {
273
+ // status of the active transport
274
+ $transport = $transportRegistry->getActiveTransport();
275
+ $this->addToDiagnostics( 'Postman Active Transport', sprintf( '%s (%s)', $transport->getName(), $transportRegistry->getPublicTransportUri( $transport ) ) );
276
+ $this->addToDiagnostics( 'Postman Active Transport Status (Ready|Connected)', ($transport->isConfiguredAndReady() ? 'Yes' : 'No') . ' | ' . ($this->testConnectivity( $transport )) );
277
+ }
278
+ if ( $transportRegistry->getActiveTransport() != $transportRegistry->getSelectedTransport() && $transportRegistry->getSelectedTransport() != null ) {
279
+ // status of the selected transport
280
+ $transport = $transportRegistry->getSelectedTransport();
281
+ $this->addToDiagnostics( 'Postman Selected Transport', sprintf( '%s (%s)', $transport->getName(), $transportRegistry->getPublicTransportUri( $transport ) ) );
282
+ $this->addToDiagnostics( 'Postman Selected Transport Status (Ready|Connected)', ($transport->isConfiguredAndReady() ? 'Yes' : 'No') . ' | ' . ($this->testConnectivity( $transport )) );
283
+ }
284
+ $this->addToDiagnostics( 'Postman Deliveries (Success|Fail)', (PostmanState::getInstance()->getSuccessfulDeliveries()) . ' | ' . (PostmanState::getInstance()->getFailedDeliveries()) );
285
+ if ( $this->options->getConnectionTimeout() != PostmanOptions::DEFAULT_TCP_CONNECTION_TIMEOUT || $this->options->getReadTimeout() != PostmanOptions::DEFAULT_TCP_READ_TIMEOUT ) {
286
+ $this->addToDiagnostics( 'Postman TCP Timeout (Connection|Read)', $this->options->getConnectionTimeout() . ' | ' . $this->options->getReadTimeout() );
287
+ }
288
+ if ( $this->options->isMailLoggingEnabled() != PostmanOptions::DEFAULT_MAIL_LOG_ENABLED || $this->options->getMailLoggingMaxEntries() != PostmanOptions::DEFAULT_MAIL_LOG_ENTRIES || $this->options->getTranscriptSize() != PostmanOptions::DEFAULT_TRANSCRIPT_SIZE ) {
289
+ $this->addToDiagnostics( 'Postman Email Log (Enabled|Limit|Transcript Size)', ($this->options->isMailLoggingEnabled() ? 'Yes' : 'No') . ' | ' . $this->options->getMailLoggingMaxEntries() . ' | ' . $this->options->getTranscriptSize() );
290
+ }
291
+ $this->addToDiagnostics( 'Postman Run Mode', $this->options->getRunMode() == PostmanOptions::RUN_MODE_PRODUCTION ? null : $this->options->getRunMode() );
292
+ $this->addToDiagnostics( 'Postman PHP LogLevel', $this->options->getLogLevel() == PostmanLogger::ERROR_INT ? null : $this->options->getLogLevel() );
293
+ $this->addToDiagnostics( 'Postman Stealth Mode', $this->options->isStealthModeEnabled() ? 'Yes' : null );
294
+ $this->addToDiagnostics( 'Postman File Locking (Enabled|Temp Dir)', PostmanState::getInstance()->isFileLockingEnabled() ? null : 'No' . ' | ' . $this->options->getTempDirectory() );
295
+ $response = array(
296
+ 'message' => $this->diagnostics,
297
+ );
298
+ wp_send_json_success( $response );
299
+ }
300
+ }
Postman/Postman-Diagnostic-Test/postman_diagnostics.js CHANGED
@@ -1,19 +1,19 @@
1
- jQuery(document).ready(function() {
2
- getDiagnosticData();
3
- });
4
-
5
- /**
6
- */
7
- function getDiagnosticData() {
8
- var data = {
9
- 'action' : 'postman_diagnostics',
10
- 'security' : jQuery('#security').val()
11
- };
12
- jQuery.post(ajaxurl, data, function(response) {
13
- if (response.success) {
14
- jQuery('#diagnostic-text').val(response.data.message);
15
- }
16
- }).fail(function(response) {
17
- ajaxFailed(response);
18
- });
19
- }
1
+ jQuery(document).ready(function() {
2
+ getDiagnosticData();
3
+ });
4
+
5
+ /**
6
+ */
7
+ function getDiagnosticData() {
8
+ var data = {
9
+ 'action' : 'postman_diagnostics',
10
+ 'security' : jQuery('#security').val()
11
+ };
12
+ jQuery.post(ajaxurl, data, function(response) {
13
+ if (response.success) {
14
+ jQuery('#diagnostic-text').val(response.data.message);
15
+ }
16
+ }).fail(function(response) {
17
+ ajaxFailed(response);
18
+ });
19
+ }
Postman/Postman-Email-Log/PostmanEmailLogController.php CHANGED
@@ -1,513 +1,513 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- require_once dirname(__DIR__) . '/PostmanLogFields.php';
7
- require_once 'PostmanEmailLogService.php';
8
- require_once 'PostmanEmailLogView.php';
9
-
10
- /**
11
- *
12
- * @author jasonhendriks
13
- */
14
- class PostmanEmailLogController {
15
- const RESEND_MAIL_AJAX_SLUG = 'postman_resend_mail';
16
- private $rootPluginFilenameAndPath;
17
- private $logger;
18
-
19
- /**
20
- */
21
- function __construct( $rootPluginFilenameAndPath ) {
22
- $this->rootPluginFilenameAndPath = $rootPluginFilenameAndPath;
23
- $this->logger = new PostmanLogger( get_class( $this ) );
24
- if ( PostmanOptions::getInstance()->isMailLoggingEnabled() ) {
25
- add_action( 'admin_menu', array(
26
- $this,
27
- 'postmanAddMenuItem',
28
- ),20 );
29
- } else {
30
- $this->logger->trace( 'not creating PostmanEmailLog admin menu item' );
31
- }
32
- if ( PostmanUtils::isCurrentPagePostmanAdmin( 'postman_email_log' ) ) {
33
- $this->logger->trace( 'on postman email log page' );
34
- // $this->logger->debug ( 'Registering ' . $actionName . ' Action Post handler' );
35
- add_action( 'admin_post_delete', array(
36
- $this,
37
- 'delete_log_item',
38
- ) );
39
- add_action( 'admin_post_view', array(
40
- $this,
41
- 'view_log_item',
42
- ) );
43
- add_action( 'admin_post_transcript', array(
44
- $this,
45
- 'view_transcript_log_item',
46
- ) );
47
- add_action( 'admin_init', array(
48
- $this,
49
- 'on_admin_init',
50
- ) );
51
- }
52
-
53
- add_action( 'wp_ajax_post_smtp_log_trash_all', array( $this, 'post_smtp_log_trash_all' ) );
54
-
55
- if ( is_admin() ) {
56
- $actionName = self::RESEND_MAIL_AJAX_SLUG;
57
- $fullname = 'wp_ajax_' . $actionName;
58
- // $this->logger->debug ( 'Registering ' . 'wp_ajax_' . $fullname . ' Ajax handler' );
59
- add_action( $fullname, array(
60
- $this,
61
- 'resendMail',
62
- ) );
63
- }
64
- }
65
-
66
- function post_smtp_log_trash_all() {
67
- check_admin_referer('post-smtp', 'security' );
68
-
69
- if ( ! current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_LOGS ) ) {
70
- wp_send_json_error( 'No permissions to manage Post SMTP logs.');
71
- }
72
-
73
- $purger = new PostmanEmailLogPurger();
74
- $purger->removeAll();
75
- wp_send_json_success();
76
- }
77
-
78
- /**
79
- */
80
- function on_admin_init() {
81
- $this->handleBulkAction();
82
- // register the stylesheet and javascript external resources
83
- $pluginData = apply_filters( 'postman_get_plugin_metadata', null );
84
- wp_register_script( 'postman_resend_email_script', plugins_url( 'script/postman_resend_email_sript.js', $this->rootPluginFilenameAndPath ), array(
85
- PostmanViewController::JQUERY_SCRIPT,
86
- PostmanViewController::POSTMAN_SCRIPT,
87
- ), $pluginData ['version'] );
88
- $this->handleCsvExport();
89
- }
90
-
91
- /**
92
- * Handles CSV Export
93
- *
94
- * @since 2.1.1 used implode, to prevent email logs from being broken
95
- * @version 1.0.1
96
- */
97
- function handleCsvExport() {
98
- if ( ! isset( $_GET['postman_export_csv'] ) ) {
99
- return;
100
- }
101
-
102
- if ( ! isset( $_REQUEST['post-smtp-log-nonce'] ) || ! wp_verify_nonce( $_REQUEST['post-smtp-log-nonce'], 'post-smtp' ) ) {
103
- wp_die( 'Security check' );
104
- }
105
-
106
- if ( current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_LOGS ) ) {
107
- $args = array(
108
- 'post_type' => PostmanEmailLogPostType::POSTMAN_CUSTOM_POST_TYPE_SLUG,
109
- 'post_status' => PostmanEmailLogService::POSTMAN_CUSTOM_POST_STATUS_PRIVATE,
110
- 'posts_per_page' => -1,
111
- );
112
- $logs = new WP_Query($args);
113
-
114
- if ( empty( $logs->posts ) ) {
115
- return;
116
- }
117
-
118
- header('Content-Type: text/csv');
119
- header('Content-Disposition: attachment; filename="email-logs.csv"');
120
-
121
- $fp = fopen('php://output', 'wb');
122
-
123
- $headers = array_keys( PostmanLogFields::get_instance()->get_fields() );
124
- $headers[] = 'delivery_time';
125
-
126
- fputcsv($fp, $headers);
127
-
128
- $date_format = get_option( 'date_format' );
129
- $time_format = get_option( 'time_format' );
130
-
131
- foreach ( $logs->posts as $log ) {
132
- $meta = PostmanLogFields::get_instance()->get($log->ID);
133
- $data = [];
134
- foreach ( $meta as $header => $line ) {
135
- $data[] = is_array( $line[0] ) ? implode( PostmanMessage::EOL, $line[0] ) : $line[0];
136
- }
137
- $data[] = date( "$date_format $time_format", strtotime( $log->post_date ) );
138
- fputcsv($fp, $data);
139
- }
140
-
141
- fclose($fp);
142
- die();
143
-
144
- }
145
- }
146
-
147
- /**
148
- */
149
- public function resendMail() {
150
- check_admin_referer( 'resend', 'security' );
151
-
152
- // get the email address of the recipient from the HTTP Request
153
- $postid = $this->getRequestParameter( 'email' );
154
- if ( ! empty( $postid ) ) {
155
- $meta_values = PostmanLogFields::get_instance()->get( $postid );
156
-
157
- if ( isset( $_POST['mail_to'] ) && ! empty( $_POST['mail_to'] ) ) {
158
- $emails = explode( ',', $_POST['mail_to'] );
159
- $to = array_map( 'sanitize_email', $emails );
160
- } else {
161
- $to = $meta_values ['original_to'] [0];
162
- }
163
-
164
- $success = wp_mail( $to, $meta_values ['original_subject'] [0], $meta_values ['original_message'] [0], $meta_values ['original_headers'] [0] );
165
-
166
- // Postman API: retrieve the result of sending this message from Postman
167
- $result = apply_filters( 'postman_wp_mail_result', null );
168
- $transcript = $result ['transcript'];
169
-
170
- // post-handling
171
- if ( $success ) {
172
- $this->logger->debug( 'Email was successfully re-sent' );
173
- // the message was sent successfully, generate an appropriate message for the user
174
- $statusMessage = sprintf( __( 'Your message was delivered (%d ms) to the SMTP server! Congratulations :)', 'post-smtp' ), $result ['time'] );
175
-
176
- // compose the JSON response for the caller
177
- $response = array(
178
- 'message' => $statusMessage,
179
- 'transcript' => $transcript,
180
- );
181
- $this->logger->trace( 'AJAX response' );
182
- $this->logger->trace( $response );
183
- // send the JSON response
184
- wp_send_json_success( $response );
185
- } else {
186
- $this->logger->error( 'Email was not successfully re-sent - ' . $result ['exception']->getCode() );
187
- // the message was NOT sent successfully, generate an appropriate message for the user
188
- $statusMessage = $result ['exception']->getMessage();
189
-
190
- // compose the JSON response for the caller
191
- $response = array(
192
- 'message' => $statusMessage,
193
- 'transcript' => $transcript,
194
- );
195
- $this->logger->trace( 'AJAX response' );
196
- $this->logger->trace( $response );
197
- // send the JSON response
198
- wp_send_json_error( $response );
199
- }
200
- } else {
201
- // compose the JSON response for the caller
202
- $response = array();
203
- // send the JSON response
204
- wp_send_json_error( $response );
205
- }
206
- }
207
-
208
- /**
209
- * TODO move this somewhere reusable
210
- *
211
- * @param mixed $parameterName
212
- * @return mixed
213
- */
214
- private function getRequestParameter( $parameterName ) {
215
- if ( isset( $_POST [ $parameterName ] ) ) {
216
- $value = filter_var( $_POST [ $parameterName ], FILTER_SANITIZE_STRING );
217
- $this->logger->trace( sprintf( 'Found parameter "%s"', $parameterName ) );
218
- $this->logger->trace( $value );
219
- return $value;
220
- }
221
- }
222
-
223
- /**
224
- * From https://www.skyverge.com/blog/add-custom-bulk-action/
225
- */
226
- function handleBulkAction() {
227
- // only do this for administrators
228
- if ( PostmanUtils::isAdmin() && isset( $_REQUEST ['email_log_entry'] ) ) {
229
- $this->logger->trace( 'handling bulk action' );
230
- if ( wp_verify_nonce( $_REQUEST ['_wpnonce'], 'bulk-email_log_entries' ) ) {
231
- $this->logger->trace( sprintf( 'nonce "%s" passed validation', sanitize_text_field($_REQUEST ['_wpnonce']) ) );
232
- if ( isset( $_REQUEST ['action'] ) && ($_REQUEST ['action'] == 'bulk_delete' || $_REQUEST ['action2'] == 'bulk_delete') ) {
233
- $this->logger->trace( sprintf( 'handling bulk delete' ) );
234
- $purger = new PostmanEmailLogPurger();
235
- $postids = array_map( 'absint', $_REQUEST ['email_log_entry'] );
236
- foreach ( $postids as $postid ) {
237
- $purger->verifyLogItemExistsAndRemove( $postid );
238
- }
239
- $mh = new PostmanMessageHandler();
240
- $mh->addMessage( __( 'Mail Log Entries were deleted.', 'post-smtp' ) );
241
- } else {
242
- $this->logger->warn( sprintf( 'action "%s" not recognized', sanitize_text_field($_REQUEST ['action']) ) );
243
- }
244
- } else {
245
- $this->logger->warn( sprintf( 'nonce "%s" failed validation', sanitize_text_field($_REQUEST ['_wpnonce']) ) );
246
- }
247
- $this->redirectToLogPage();
248
- }
249
- }
250
-
251
- /**
252
- */
253
- function delete_log_item() {
254
- // only do this for administrators
255
- if ( PostmanUtils::isAdmin() ) {
256
- $this->logger->trace( 'handling delete item' );
257
- $postid = absint($_REQUEST ['email']);
258
- if ( wp_verify_nonce( $_REQUEST ['_wpnonce'], 'delete_email_log_item_' . $postid ) ) {
259
- $this->logger->trace( sprintf( 'nonce "%s" passed validation', sanitize_text_field($_REQUEST ['_wpnonce']) ) );
260
- $purger = new PostmanEmailLogPurger();
261
- $purger->verifyLogItemExistsAndRemove( $postid );
262
- $mh = new PostmanMessageHandler();
263
- $mh->addMessage( __( 'Mail Log Entry was deleted.', 'post-smtp' ) );
264
- } else {
265
- $this->logger->warn( sprintf( 'nonce "%s" failed validation', sanitize_text_field($_REQUEST ['_wpnonce']) ) );
266
- }
267
- $this->redirectToLogPage();
268
- }
269
- }
270
-
271
- /**
272
- */
273
- function view_log_item() {
274
- // only do this for administrators
275
- if ( PostmanUtils::isAdmin() ) {
276
- $this->logger->trace( 'handling view item' );
277
- $postid = absint( $_REQUEST ['email'] );
278
- $post = get_post( $postid );
279
-
280
- if ( $post->post_type !== 'postman_sent_mail' ) {
281
- return;
282
- }
283
-
284
- $meta_values = PostmanLogFields::get_instance()->get( $postid );
285
- // https://css-tricks.com/examples/hrs/
286
- print '<html><head><style>body {font-family: monospace;} hr {
287
- border: 0;
288
- border-bottom: 1px dashed #ccc;
289
- background: #bbb;
290
- }</style></head><body>';
291
- print '<table>';
292
- if ( ! empty( $meta_values ['from_header'] [0] ) ) {
293
- printf( '<tr><th style="text-align:right">%s:</th><td>%s</td></tr>', _x( 'From', 'Who is this message From?', 'post-smtp' ), esc_html( $meta_values ['from_header'] [0] ) );
294
- }
295
- // show the To header (it's optional)
296
- if ( ! empty( $meta_values ['to_header'] [0] ) ) {
297
- printf( '<tr><th style="text-align:right">%s:</th><td>%s</td></tr>', _x( 'To', 'Who is this message To?', 'post-smtp' ), esc_html( $meta_values ['to_header'] [0] ) );
298
- }
299
- // show the Cc header (it's optional)
300
- if ( ! empty( $meta_values ['cc_header'] [0] ) ) {
301
- printf( '<tr><th style="text-align:right">%s:</th><td>%s</td></tr>', _x( 'Cc', 'Who is this message Cc\'d to?', 'post-smtp' ), esc_html( $meta_values ['cc_header'] [0] ) );
302
- }
303
- // show the Bcc header (it's optional)
304
- if ( ! empty( $meta_values ['bcc_header'] [0] ) ) {
305
- printf( '<tr><th style="text-align:right">%s:</th><td>%s</td></tr>', _x( 'Bcc', 'Who is this message Bcc\'d to?', 'post-smtp' ), esc_html( $meta_values ['bcc_header'] [0] ) );
306
- }
307
- // show the Reply-To header (it's optional)
308
- if ( ! empty( $meta_values ['reply_to_header'] [0] ) ) {
309
- printf( '<tr><th style="text-align:right">%s:</th><td>%s</td></tr>', __( 'Reply-To', 'post-smtp' ), esc_html( $meta_values ['reply_to_header'] [0] ) );
310
- }
311
- printf( '<tr><th style="text-align:right">%s:</th><td>%s</td></tr>', _x( 'Date', 'What is the date today?', 'post-smtp' ), $post->post_date );
312
- printf( '<tr><th style="text-align:right">%s:</th><td>%s</td></tr>', _x( 'Subject', 'What is the subject of this message?', 'post-smtp' ), esc_html( $post->post_title ) );
313
- // The Transport UI is always there, in more recent versions that is
314
- if ( ! empty( $meta_values ['transport_uri'] [0] ) ) {
315
- printf( '<tr><th style="text-align:right">%s:</th><td>%s</td></tr>', _x( 'Delivery-URI', 'What is the unique URI of the configuration?', 'post-smtp' ), esc_html( $meta_values ['transport_uri'] [0] ) );
316
- }
317
- print '</table>';
318
- print '<hr/>';
319
- print '<pre>';
320
- print $this->sanitize_message( $post->post_content );
321
- print '</pre>';
322
- print '</body></html>';
323
- die();
324
- }
325
- }
326
-
327
- function sanitize_message( $message ) {
328
- $allowed_tags = wp_kses_allowed_html( 'post' );
329
- $allowed_tags['style'] = array();
330
-
331
- return wp_kses( $message, $allowed_tags );
332
- }
333
-
334
- /**
335
- */
336
- function view_transcript_log_item() {
337
- // only do this for administrators
338
- if ( PostmanUtils::isAdmin() ) {
339
- $this->logger->trace( 'handling view transcript item' );
340
- $postid = absint($_REQUEST ['email']);
341
- $post = get_post( $postid );
342
- $meta_values = PostmanLogFields::get_instance()->get( $postid );
343
- // https://css-tricks.com/examples/hrs/
344
- print '<html><head><style>body {font-family: monospace;} hr {
345
- border: 0;
346
- border-bottom: 1px dashed #ccc;
347
- background: #bbb;
348
- }</style></head><body>';
349
- printf( '<p>%s</p>', __( 'This is the conversation between Postman and the mail server. It can be useful for diagnosing problems. <b>DO NOT</b> post it on-line, it may contain your account password.', 'post-smtp' ) );
350
- print '<hr/>';
351
- print '<pre>';
352
- if ( ! empty( $meta_values ['session_transcript'] [0] ) ) {
353
- print esc_html( $meta_values ['session_transcript'] [0] );
354
- } else {
355
- /* Translators: Meaning "Not Applicable" */
356
- print __( 'n/a', 'post-smtp' );
357
- }
358
- print '</pre>';
359
- print '</body></html>';
360
- die();
361
- }
362
- }
363
-
364
- /**
365
- * For whatever reason, PostmanUtils::get..url doesn't work here? :(
366
- */
367
- function redirectToLogPage() {
368
- PostmanUtils::redirect( PostmanUtils::POSTMAN_EMAIL_LOG_PAGE_RELATIVE_URL );
369
- die();
370
- }
371
-
372
- /**
373
- * Register the page
374
- */
375
- function postmanAddMenuItem() {
376
- // only do this for administrators
377
- if ( PostmanUtils::isAdmin() ) {
378
- $this->logger->trace( 'created PostmanEmailLog admin menu item' );
379
- /*
380
- Translators where (%s) is the name of the plugin */
381
- $pageTitle = sprintf( __( '%s Email Log', 'post-smtp' ), __( 'Post SMTP', 'post-smtp' ) );
382
- $pluginName = _x( 'Email Log', 'The log of Emails that have been delivered', 'post-smtp' );
383
-
384
- $page = add_submenu_page( PostmanViewController::POSTMAN_MENU_SLUG, $pageTitle, $pluginName, Postman::MANAGE_POSTMAN_CAPABILITY_LOGS, 'postman_email_log', array( $this, 'postman_render_email_page' ) );
385
-
386
- // When the plugin options page is loaded, also load the stylesheet
387
- add_action( 'admin_print_styles-' . $page, array(
388
- $this,
389
- 'postman_email_log_enqueue_resources',
390
- ) );
391
- }
392
- }
393
-
394
- /**
395
- * Enqueus Styles/ Scripts
396
- *
397
- * @since 2.1 Changed stylesheet
398
- * @version 1.0
399
- */
400
- function postman_email_log_enqueue_resources() {
401
-
402
- wp_enqueue_style( PostmanViewController::POSTMAN_STYLE );
403
- wp_enqueue_script( 'postman_resend_email_script' );
404
- wp_enqueue_script( 'sprintf' );
405
-
406
- }
407
-
408
- /**
409
- * *************************** RENDER TEST PAGE ********************************
410
- * ******************************************************************************
411
- * This function renders the admin page and the example list table.
412
- * Although it's
413
- * possible to call prepare_items() and display() from the constructor, there
414
- * are often times where you may need to include logic here between those steps,
415
- * so we've instead called those methods explicitly. It keeps things flexible, and
416
- * it's the way the list tables are used in the WordPress core.
417
- */
418
- function postman_render_email_page() {
419
-
420
- // Create an instance of our package class...
421
- $testListTable = new PostmanEmailLogView();
422
- wp_enqueue_script( 'postman_resend_email_script' );
423
- // Fetch, prepare, sort, and filter our data...
424
- $testListTable->prepare_items();
425
-
426
- ?>
427
- <div class="wrap">
428
-
429
- <div id="icon-users" class="icon32">
430
- <br />
431
- </div>
432
- <h2><?php
433
- /* Translators where (%s) is the name of the plugin */
434
- echo sprintf( __( '%s Email Log', 'post-smtp' ), __( 'Post SMTP', 'post-smtp' ) )?></h2>
435
-
436
- <?php //include_once POST_SMTP_PATH . '/Postman/extra/donation.php'; ?>
437
-
438
- <div class="ps-config-bar">
439
- <p><?php
440
-
441
- echo __( 'This is a record of deliveries made to the mail server. It does not neccessarily indicate sucessful delivery to the recipient.', 'post-smtp' )?></p>
442
- </div>
443
-
444
- <?php
445
- $from_date = isset( $_GET['from_date'] ) ? sanitize_text_field( $_GET['from_date'] ) : '';
446
- $to_date = isset( $_GET['to_date'] ) ? sanitize_text_field( $_GET['to_date'] ) : '';
447
- $search = isset( $_GET['search'] ) ? sanitize_text_field( $_GET['search'] ) : '';
448
- $page_records = apply_filters( 'postman_log_per_page', array( 10, 15, 25, 50, 75, 100 ) );
449
- $postman_page_records = isset( $_GET['postman_page_records'] ) ? absint( $_GET['postman_page_records'] ) : '';
450
- ?>
451
-
452
- <form id="postman-email-log-filter" action="<?php echo admin_url( PostmanUtils::POSTMAN_EMAIL_LOG_PAGE_RELATIVE_URL ); ?>" method="get">
453
- <input type="hidden" name="page" value="postman_email_log">
454
- <input type="hidden" name="post-smtp-filter" value="1">
455
- <?php wp_nonce_field('post-smtp', 'post-smtp-log-nonce'); ?>
456
-
457
- <div id="email-log-filter" class="postman-log-row">
458
- <div class="form-control">
459
- <label for="from_date"><?php _e( 'From Date', 'post-smtp' ); ?></label>
460
- <input id="from_date" class="email-log-date" value="<?php echo esc_attr($from_date); ?>" type="text" name="from_date" placeholder="<?php _e( 'From Date', 'post-smtp' ); ?>">
461
- </div>
462
- <div class="form-control">
463
- <label for="to_date"><?php _e( 'To Date', 'post-smtp' ); ?></label>
464
- <input id="to_date" class="email-log-date" value="<?php echo esc_attr($to_date); ?>" type="text" name="to_date" placeholder="<?php _e( 'To Date', 'post-smtp' ); ?>">
465
- </div>
466
- <div class="form-control">
467
- <label for="search"><?php _e( 'Search', 'post-smtp' ); ?></label>
468
- <input id="search" type="text" name="search" value="<?php echo esc_attr($search); ?>" placeholder="<?php _e( 'Search', 'post-smtp' ); ?>">
469
- </div>
470
- <div class="form-control">
471
- <label id="postman_page_records"><?php _e( 'Records per page', 'post-smtp' ); ?></label>
472
- <select id="postman_page_records" name="postman_page_records">
473
- <?php
474
- foreach ( $page_records as $value ) {
475
- $selected = selected( $postman_page_records, $value, false );
476
- echo '<option value="' . $value . '"' . $selected . '>' . $value . '</option>';
477
- }
478
- ?>
479
- </select>
480
- </div>
481
-
482
- <div class="form-control" style="padding: 0 5px 0 5px;">
483
- <button type="submit" name="filter" class="ps-btn-orange"><?php _e( 'Filter/Search', 'post-smtp' ); ?></button>
484
- </div>
485
-
486
- <div class="form-control" style="padding: 0 5px 0 0px;">
487
- <button type="submit" id="postman_export_csv" name="postman_export_csv" class="ps-btn-orange"><?php _e( 'Export To CSV', 'post-smtp' ); ?></button>
488
- </div>
489
-
490
- <div class="form-control">
491
- <button type="submit" id="postman_trash_all" name="postman_trash_all" class="ps-btn-red"><?php _e( 'Trash All', 'post-smtp' ); ?></button>
492
- </div>
493
-
494
- </div>
495
- <div class="error">Please notice: when you select a date for example 11/20/2017, behind the scene the query select <b>11/20/2017 00:00:00</b>.<br>So if you searching for an email arrived that day at any hour you need to select 11/20/2017 as the <b>From Date</b> and 11/21/2017 as the <b>To Date</b>.</div>
496
- </form>
497
-
498
- <!-- Forms are NOT created automatically, so you need to wrap the table in one to use features like bulk actions -->
499
- <form id="movies-filter" method="get">
500
- <!-- For plugins, we also need to ensure that the form posts back to our current page -->
501
- <input type="hidden" name="page"
502
- value="<?php echo filter_input( INPUT_GET, 'page', FILTER_SANITIZE_STRING ); ?>" />
503
-
504
- <!-- Now we can render the completed list table -->
505
- <?php $testListTable->display()?>
506
- </form>
507
-
508
- <?php add_thickbox(); ?>
509
-
510
- </div>
511
- <?php
512
- }
513
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ require_once dirname(__DIR__) . '/PostmanLogFields.php';
7
+ require_once 'PostmanEmailLogService.php';
8
+ require_once 'PostmanEmailLogView.php';
9
+
10
+ /**
11
+ *
12
+ * @author jasonhendriks
13
+ */
14
+ class PostmanEmailLogController {
15
+ const RESEND_MAIL_AJAX_SLUG = 'postman_resend_mail';
16
+ private $rootPluginFilenameAndPath;
17
+ private $logger;
18
+
19
+ /**
20
+ */
21
+ function __construct( $rootPluginFilenameAndPath ) {
22
+ $this->rootPluginFilenameAndPath = $rootPluginFilenameAndPath;
23
+ $this->logger = new PostmanLogger( get_class( $this ) );
24
+ if ( PostmanOptions::getInstance()->isMailLoggingEnabled() ) {
25
+ add_action( 'admin_menu', array(
26
+ $this,
27
+ 'postmanAddMenuItem',
28
+ ),20 );
29
+ } else {
30
+ $this->logger->trace( 'not creating PostmanEmailLog admin menu item' );
31
+ }
32
+ if ( PostmanUtils::isCurrentPagePostmanAdmin( 'postman_email_log' ) ) {
33
+ $this->logger->trace( 'on postman email log page' );
34
+ // $this->logger->debug ( 'Registering ' . $actionName . ' Action Post handler' );
35
+ add_action( 'admin_post_delete', array(
36
+ $this,
37
+ 'delete_log_item',
38
+ ) );
39
+ add_action( 'admin_post_view', array(
40
+ $this,
41
+ 'view_log_item',
42
+ ) );
43
+ add_action( 'admin_post_transcript', array(
44
+ $this,
45
+ 'view_transcript_log_item',
46
+ ) );
47
+ add_action( 'admin_init', array(
48
+ $this,
49
+ 'on_admin_init',
50
+ ) );
51
+ }
52
+
53
+ add_action( 'wp_ajax_post_smtp_log_trash_all', array( $this, 'post_smtp_log_trash_all' ) );
54
+
55
+ if ( is_admin() ) {
56
+ $actionName = self::RESEND_MAIL_AJAX_SLUG;
57
+ $fullname = 'wp_ajax_' . $actionName;
58
+ // $this->logger->debug ( 'Registering ' . 'wp_ajax_' . $fullname . ' Ajax handler' );
59
+ add_action( $fullname, array(
60
+ $this,
61
+ 'resendMail',
62
+ ) );
63
+ }
64
+ }
65
+
66
+ function post_smtp_log_trash_all() {
67
+ check_admin_referer('post-smtp', 'security' );
68
+
69
+ if ( ! current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_LOGS ) ) {
70
+ wp_send_json_error( 'No permissions to manage Post SMTP logs.');
71
+ }
72
+
73
+ $purger = new PostmanEmailLogPurger();
74
+ $purger->removeAll();
75
+ wp_send_json_success();
76
+ }
77
+
78
+ /**
79
+ */
80
+ function on_admin_init() {
81
+ $this->handleBulkAction();
82
+ // register the stylesheet and javascript external resources
83
+ $pluginData = apply_filters( 'postman_get_plugin_metadata', null );
84
+ wp_register_script( 'postman_resend_email_script', plugins_url( 'script/postman_resend_email_sript.js', $this->rootPluginFilenameAndPath ), array(
85
+ PostmanViewController::JQUERY_SCRIPT,
86
+ PostmanViewController::POSTMAN_SCRIPT,
87
+ ), $pluginData ['version'] );
88
+ $this->handleCsvExport();
89
+ }
90
+
91
+ /**
92
+ * Handles CSV Export
93
+ *
94
+ * @since 2.1.1 used implode, to prevent email logs from being broken
95
+ * @version 1.0.1
96
+ */
97
+ function handleCsvExport() {
98
+ if ( ! isset( $_GET['postman_export_csv'] ) ) {
99
+ return;
100
+ }
101
+
102
+ if ( ! isset( $_REQUEST['post-smtp-log-nonce'] ) || ! wp_verify_nonce( $_REQUEST['post-smtp-log-nonce'], 'post-smtp' ) ) {
103
+ wp_die( 'Security check' );
104
+ }
105
+
106
+ if ( current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_LOGS ) ) {
107
+ $args = array(
108
+ 'post_type' => PostmanEmailLogPostType::POSTMAN_CUSTOM_POST_TYPE_SLUG,
109
+ 'post_status' => PostmanEmailLogService::POSTMAN_CUSTOM_POST_STATUS_PRIVATE,
110
+ 'posts_per_page' => -1,
111
+ );
112
+ $logs = new WP_Query($args);
113
+
114
+ if ( empty( $logs->posts ) ) {
115
+ return;
116
+ }
117
+
118
+ header('Content-Type: text/csv');
119
+ header('Content-Disposition: attachment; filename="email-logs.csv"');
120
+
121
+ $fp = fopen('php://output', 'wb');
122
+
123
+ $headers = array_keys( PostmanLogFields::get_instance()->get_fields() );
124
+ $headers[] = 'delivery_time';
125
+
126
+ fputcsv($fp, $headers);
127
+
128
+ $date_format = get_option( 'date_format' );
129
+ $time_format = get_option( 'time_format' );
130
+
131
+ foreach ( $logs->posts as $log ) {
132
+ $meta = PostmanLogFields::get_instance()->get($log->ID);
133
+ $data = [];
134
+ foreach ( $meta as $header => $line ) {
135
+ $data[] = is_array( $line[0] ) ? implode( PostmanMessage::EOL, $line[0] ) : $line[0];
136
+ }
137
+ $data[] = date( "$date_format $time_format", strtotime( $log->post_date ) );
138
+ fputcsv($fp, $data);
139
+ }
140
+
141
+ fclose($fp);
142
+ die();
143
+
144
+ }
145
+ }
146
+
147
+ /**
148
+ */
149
+ public function resendMail() {
150
+ check_admin_referer( 'resend', 'security' );
151
+
152
+ // get the email address of the recipient from the HTTP Request
153
+ $postid = $this->getRequestParameter( 'email' );
154
+ if ( ! empty( $postid ) ) {
155
+ $meta_values = PostmanLogFields::get_instance()->get( $postid );
156
+
157
+ if ( isset( $_POST['mail_to'] ) && ! empty( $_POST['mail_to'] ) ) {
158
+ $emails = explode( ',', $_POST['mail_to'] );
159
+ $to = array_map( 'sanitize_email', $emails );
160
+ } else {
161
+ $to = $meta_values ['original_to'] [0];
162
+ }
163
+
164
+ $success = wp_mail( $to, $meta_values ['original_subject'] [0], $meta_values ['original_message'] [0], $meta_values ['original_headers'] [0] );
165
+
166
+ // Postman API: retrieve the result of sending this message from Postman
167
+ $result = apply_filters( 'postman_wp_mail_result', null );
168
+ $transcript = $result ['transcript'];
169
+
170
+ // post-handling
171
+ if ( $success ) {
172
+ $this->logger->debug( 'Email was successfully re-sent' );
173
+ // the message was sent successfully, generate an appropriate message for the user
174
+ $statusMessage = sprintf( __( 'Your message was delivered (%d ms) to the SMTP server! Congratulations :)', 'post-smtp' ), $result ['time'] );
175
+
176
+ // compose the JSON response for the caller
177
+ $response = array(
178
+ 'message' => $statusMessage,
179
+ 'transcript' => $transcript,
180
+ );
181
+ $this->logger->trace( 'AJAX response' );
182
+ $this->logger->trace( $response );
183
+ // send the JSON response
184
+ wp_send_json_success( $response );
185
+ } else {
186
+ $this->logger->error( 'Email was not successfully re-sent - ' . $result ['exception']->getCode() );
187
+ // the message was NOT sent successfully, generate an appropriate message for the user
188
+ $statusMessage = $result ['exception']->getMessage();
189
+
190
+ // compose the JSON response for the caller
191
+ $response = array(
192
+ 'message' => $statusMessage,
193
+ 'transcript' => $transcript,
194
+ );
195
+ $this->logger->trace( 'AJAX response' );
196
+ $this->logger->trace( $response );
197
+ // send the JSON response
198
+ wp_send_json_error( $response );
199
+ }
200
+ } else {
201
+ // compose the JSON response for the caller
202
+ $response = array();
203
+ // send the JSON response
204
+ wp_send_json_error( $response );
205
+ }
206
+ }
207
+
208
+ /**
209
+ * TODO move this somewhere reusable
210
+ *
211
+ * @param mixed $parameterName
212
+ * @return mixed
213
+ */
214
+ private function getRequestParameter( $parameterName ) {
215
+ if ( isset( $_POST [ $parameterName ] ) ) {
216
+ $value = filter_var( $_POST [ $parameterName ], FILTER_SANITIZE_STRING );
217
+ $this->logger->trace( sprintf( 'Found parameter "%s"', $parameterName ) );
218
+ $this->logger->trace( $value );
219
+ return $value;
220
+ }
221
+ }
222
+
223
+ /**
224
+ * From https://www.skyverge.com/blog/add-custom-bulk-action/
225
+ */
226
+ function handleBulkAction() {
227
+ // only do this for administrators
228
+ if ( PostmanUtils::isAdmin() && isset( $_REQUEST ['email_log_entry'] ) ) {
229
+ $this->logger->trace( 'handling bulk action' );
230
+ if ( wp_verify_nonce( $_REQUEST ['_wpnonce'], 'bulk-email_log_entries' ) ) {
231
+ $this->logger->trace( sprintf( 'nonce "%s" passed validation', sanitize_text_field($_REQUEST ['_wpnonce']) ) );
232
+ if ( isset( $_REQUEST ['action'] ) && ($_REQUEST ['action'] == 'bulk_delete' || $_REQUEST ['action2'] == 'bulk_delete') ) {
233
+ $this->logger->trace( sprintf( 'handling bulk delete' ) );
234
+ $purger = new PostmanEmailLogPurger();
235
+ $postids = array_map( 'absint', $_REQUEST ['email_log_entry'] );
236
+ foreach ( $postids as $postid ) {
237
+ $purger->verifyLogItemExistsAndRemove( $postid );
238
+ }
239
+ $mh = new PostmanMessageHandler();
240
+ $mh->addMessage( __( 'Mail Log Entries were deleted.', 'post-smtp' ) );
241
+ } else {
242
+ $this->logger->warn( sprintf( 'action "%s" not recognized', sanitize_text_field($_REQUEST ['action']) ) );
243
+ }
244
+ } else {
245
+ $this->logger->warn( sprintf( 'nonce "%s" failed validation', sanitize_text_field($_REQUEST ['_wpnonce']) ) );
246
+ }
247
+ $this->redirectToLogPage();
248
+ }
249
+ }
250
+
251
+ /**
252
+ */
253
+ function delete_log_item() {
254
+ // only do this for administrators
255
+ if ( PostmanUtils::isAdmin() ) {
256
+ $this->logger->trace( 'handling delete item' );
257
+ $postid = absint($_REQUEST ['email']);
258
+ if ( wp_verify_nonce( $_REQUEST ['_wpnonce'], 'delete_email_log_item_' . $postid ) ) {
259
+ $this->logger->trace( sprintf( 'nonce "%s" passed validation', sanitize_text_field($_REQUEST ['_wpnonce']) ) );
260
+ $purger = new PostmanEmailLogPurger();
261
+ $purger->verifyLogItemExistsAndRemove( $postid );
262
+ $mh = new PostmanMessageHandler();
263
+ $mh->addMessage( __( 'Mail Log Entry was deleted.', 'post-smtp' ) );
264
+ } else {
265
+ $this->logger->warn( sprintf( 'nonce "%s" failed validation', sanitize_text_field($_REQUEST ['_wpnonce']) ) );
266
+ }
267
+ $this->redirectToLogPage();
268
+ }
269
+ }
270
+
271
+ /**
272
+ */
273
+ function view_log_item() {
274
+ // only do this for administrators
275
+ if ( PostmanUtils::isAdmin() ) {
276
+ $this->logger->trace( 'handling view item' );
277
+ $postid = absint( $_REQUEST ['email'] );
278
+ $post = get_post( $postid );
279
+
280
+ if ( $post->post_type !== 'postman_sent_mail' ) {
281
+ return;
282
+ }
283
+
284
+ $meta_values = PostmanLogFields::get_instance()->get( $postid );
285
+ // https://css-tricks.com/examples/hrs/
286
+ print '<html><head><style>body {font-family: monospace;} hr {
287
+ border: 0;
288
+ border-bottom: 1px dashed #ccc;
289
+ background: #bbb;
290
+ }</style></head><body>';
291
+ print '<table>';
292
+ if ( ! empty( $meta_values ['from_header'] [0] ) ) {
293
+ printf( '<tr><th style="text-align:right">%s:</th><td>%s</td></tr>', _x( 'From', 'Who is this message From?', 'post-smtp' ), esc_html( $meta_values ['from_header'] [0] ) );
294
+ }
295
+ // show the To header (it's optional)
296
+ if ( ! empty( $meta_values ['to_header'] [0] ) ) {
297
+ printf( '<tr><th style="text-align:right">%s:</th><td>%s</td></tr>', _x( 'To', 'Who is this message To?', 'post-smtp' ), esc_html( $meta_values ['to_header'] [0] ) );
298
+ }
299
+ // show the Cc header (it's optional)
300
+ if ( ! empty( $meta_values ['cc_header'] [0] ) ) {
301
+ printf( '<tr><th style="text-align:right">%s:</th><td>%s</td></tr>', _x( 'Cc', 'Who is this message Cc\'d to?', 'post-smtp' ), esc_html( $meta_values ['cc_header'] [0] ) );
302
+ }
303
+ // show the Bcc header (it's optional)
304
+ if ( ! empty( $meta_values ['bcc_header'] [0] ) ) {
305
+ printf( '<tr><th style="text-align:right">%s:</th><td>%s</td></tr>', _x( 'Bcc', 'Who is this message Bcc\'d to?', 'post-smtp' ), esc_html( $meta_values ['bcc_header'] [0] ) );
306
+ }
307
+ // show the Reply-To header (it's optional)
308
+ if ( ! empty( $meta_values ['reply_to_header'] [0] ) ) {
309
+ printf( '<tr><th style="text-align:right">%s:</th><td>%s</td></tr>', __( 'Reply-To', 'post-smtp' ), esc_html( $meta_values ['reply_to_header'] [0] ) );
310
+ }
311
+ printf( '<tr><th style="text-align:right">%s:</th><td>%s</td></tr>', _x( 'Date', 'What is the date today?', 'post-smtp' ), $post->post_date );
312
+ printf( '<tr><th style="text-align:right">%s:</th><td>%s</td></tr>', _x( 'Subject', 'What is the subject of this message?', 'post-smtp' ), esc_html( $post->post_title ) );
313
+ // The Transport UI is always there, in more recent versions that is
314
+ if ( ! empty( $meta_values ['transport_uri'] [0] ) ) {
315
+ printf( '<tr><th style="text-align:right">%s:</th><td>%s</td></tr>', _x( 'Delivery-URI', 'What is the unique URI of the configuration?', 'post-smtp' ), esc_html( $meta_values ['transport_uri'] [0] ) );
316
+ }
317
+ print '</table>';
318
+ print '<hr/>';
319
+ print '<pre>';
320
+ print $this->sanitize_message( $post->post_content );
321
+ print '</pre>';
322
+ print '</body></html>';
323
+ die();
324
+ }
325
+ }
326
+
327
+ function sanitize_message( $message ) {
328
+ $allowed_tags = wp_kses_allowed_html( 'post' );
329
+ $allowed_tags['style'] = array();
330
+
331
+ return wp_kses( $message, $allowed_tags );
332
+ }
333
+
334
+ /**
335
+ */
336
+ function view_transcript_log_item() {
337
+ // only do this for administrators
338
+ if ( PostmanUtils::isAdmin() ) {
339
+ $this->logger->trace( 'handling view transcript item' );
340
+ $postid = absint($_REQUEST ['email']);
341
+ $post = get_post( $postid );
342
+ $meta_values = PostmanLogFields::get_instance()->get( $postid );
343
+ // https://css-tricks.com/examples/hrs/
344
+ print '<html><head><style>body {font-family: monospace;} hr {
345
+ border: 0;
346
+ border-bottom: 1px dashed #ccc;
347
+ background: #bbb;
348
+ }</style></head><body>';
349
+ printf( '<p>%s</p>', __( 'This is the conversation between Postman and the mail server. It can be useful for diagnosing problems. <b>DO NOT</b> post it on-line, it may contain your account password.', 'post-smtp' ) );
350
+ print '<hr/>';
351
+ print '<pre>';
352
+ if ( ! empty( $meta_values ['session_transcript'] [0] ) ) {
353
+ print esc_html( $meta_values ['session_transcript'] [0] );
354
+ } else {
355
+ /* Translators: Meaning "Not Applicable" */
356
+ print __( 'n/a', 'post-smtp' );
357
+ }
358
+ print '</pre>';
359
+ print '</body></html>';
360
+ die();
361
+ }
362
+ }
363
+
364
+ /**
365
+ * For whatever reason, PostmanUtils::get..url doesn't work here? :(
366
+ */
367
+ function redirectToLogPage() {
368
+ PostmanUtils::redirect( PostmanUtils::POSTMAN_EMAIL_LOG_PAGE_RELATIVE_URL );
369
+ die();
370
+ }
371
+
372
+ /**
373
+ * Register the page
374
+ */
375
+ function postmanAddMenuItem() {
376
+ // only do this for administrators
377
+ if ( PostmanUtils::isAdmin() ) {
378
+ $this->logger->trace( 'created PostmanEmailLog admin menu item' );
379
+ /*
380
+ Translators where (%s) is the name of the plugin */
381
+ $pageTitle = sprintf( __( '%s Email Log', 'post-smtp' ), __( 'Post SMTP', 'post-smtp' ) );
382
+ $pluginName = _x( 'Email Log', 'The log of Emails that have been delivered', 'post-smtp' );
383
+
384
+ $page = add_submenu_page( PostmanViewController::POSTMAN_MENU_SLUG, $pageTitle, $pluginName, Postman::MANAGE_POSTMAN_CAPABILITY_LOGS, 'postman_email_log', array( $this, 'postman_render_email_page' ) );
385
+
386
+ // When the plugin options page is loaded, also load the stylesheet
387
+ add_action( 'admin_print_styles-' . $page, array(
388
+ $this,
389
+ 'postman_email_log_enqueue_resources',
390
+ ) );
391
+ }
392
+ }
393
+
394
+ /**
395
+ * Enqueus Styles/ Scripts
396
+ *
397
+ * @since 2.1 Changed stylesheet
398
+ * @version 1.0
399
+ */
400
+ function postman_email_log_enqueue_resources() {
401
+
402
+ wp_enqueue_style( PostmanViewController::POSTMAN_STYLE );
403
+ wp_enqueue_script( 'postman_resend_email_script' );
404
+ wp_enqueue_script( 'sprintf' );
405
+
406
+ }
407
+
408
+ /**
409
+ * *************************** RENDER TEST PAGE ********************************
410
+ * ******************************************************************************
411
+ * This function renders the admin page and the example list table.
412
+ * Although it's
413
+ * possible to call prepare_items() and display() from the constructor, there
414
+ * are often times where you may need to include logic here between those steps,
415
+ * so we've instead called those methods explicitly. It keeps things flexible, and
416
+ * it's the way the list tables are used in the WordPress core.
417
+ */
418
+ function postman_render_email_page() {
419
+
420
+ // Create an instance of our package class...
421
+ $testListTable = new PostmanEmailLogView();
422
+ wp_enqueue_script( 'postman_resend_email_script' );
423
+ // Fetch, prepare, sort, and filter our data...
424
+ $testListTable->prepare_items();
425
+
426
+ ?>
427
+ <div class="wrap">
428
+
429
+ <div id="icon-users" class="icon32">
430
+ <br />
431
+ </div>
432
+ <h2><?php
433
+ /* Translators where (%s) is the name of the plugin */
434
+ echo sprintf( __( '%s Email Log', 'post-smtp' ), __( 'Post SMTP', 'post-smtp' ) )?></h2>
435
+
436
+ <?php //include_once POST_SMTP_PATH . '/Postman/extra/donation.php'; ?>
437
+
438
+ <div class="ps-config-bar">
439
+ <p><?php
440
+
441
+ echo __( 'This is a record of deliveries made to the mail server. It does not neccessarily indicate sucessful delivery to the recipient.', 'post-smtp' )?></p>
442
+ </div>
443
+
444
+ <?php
445
+ $from_date = isset( $_GET['from_date'] ) ? sanitize_text_field( $_GET['from_date'] ) : '';
446
+ $to_date = isset( $_GET['to_date'] ) ? sanitize_text_field( $_GET['to_date'] ) : '';
447
+ $search = isset( $_GET['search'] ) ? sanitize_text_field( $_GET['search'] ) : '';
448
+ $page_records = apply_filters( 'postman_log_per_page', array( 10, 15, 25, 50, 75, 100 ) );
449
+ $postman_page_records = isset( $_GET['postman_page_records'] ) ? absint( $_GET['postman_page_records'] ) : '';
450
+ ?>
451
+
452
+ <form id="postman-email-log-filter" action="<?php echo admin_url( PostmanUtils::POSTMAN_EMAIL_LOG_PAGE_RELATIVE_URL ); ?>" method="get">
453
+ <input type="hidden" name="page" value="postman_email_log">
454
+ <input type="hidden" name="post-smtp-filter" value="1">
455
+ <?php wp_nonce_field('post-smtp', 'post-smtp-log-nonce'); ?>
456
+
457
+ <div id="email-log-filter" class="postman-log-row">
458
+ <div class="form-control">
459
+ <label for="from_date"><?php _e( 'From Date', 'post-smtp' ); ?></label>
460
+ <input id="from_date" class="email-log-date" value="<?php echo esc_attr($from_date); ?>" type="text" name="from_date" placeholder="<?php _e( 'From Date', 'post-smtp' ); ?>">
461
+ </div>
462
+ <div class="form-control">
463
+ <label for="to_date"><?php _e( 'To Date', 'post-smtp' ); ?></label>
464
+ <input id="to_date" class="email-log-date" value="<?php echo esc_attr($to_date); ?>" type="text" name="to_date" placeholder="<?php _e( 'To Date', 'post-smtp' ); ?>">
465
+ </div>
466
+ <div class="form-control">
467
+ <label for="search"><?php _e( 'Search', 'post-smtp' ); ?></label>
468
+ <input id="search" type="text" name="search" value="<?php echo esc_attr($search); ?>" placeholder="<?php _e( 'Search', 'post-smtp' ); ?>">
469
+ </div>
470
+ <div class="form-control">
471
+ <label id="postman_page_records"><?php _e( 'Records per page', 'post-smtp' ); ?></label>
472
+ <select id="postman_page_records" name="postman_page_records">
473
+ <?php
474
+ foreach ( $page_records as $value ) {
475
+ $selected = selected( $postman_page_records, $value, false );
476
+ echo '<option value="' . $value . '"' . $selected . '>' . $value . '</option>';
477
+ }
478
+ ?>
479
+ </select>
480
+ </div>
481
+
482
+ <div class="form-control" style="padding: 0 5px 0 5px;">
483
+ <button type="submit" name="filter" class="ps-btn-orange"><?php _e( 'Filter/Search', 'post-smtp' ); ?></button>
484
+ </div>
485
+
486
+ <div class="form-control" style="padding: 0 5px 0 0px;">
487
+ <button type="submit" id="postman_export_csv" name="postman_export_csv" class="ps-btn-orange"><?php _e( 'Export To CSV', 'post-smtp' ); ?></button>
488
+ </div>
489
+
490
+ <div class="form-control">
491
+ <button type="submit" id="postman_trash_all" name="postman_trash_all" class="ps-btn-red"><?php _e( 'Trash All', 'post-smtp' ); ?></button>
492
+ </div>
493
+
494
+ </div>
495
+ <div class="error">Please notice: when you select a date for example 11/20/2017, behind the scene the query select <b>11/20/2017 00:00:00</b>.<br>So if you searching for an email arrived that day at any hour you need to select 11/20/2017 as the <b>From Date</b> and 11/21/2017 as the <b>To Date</b>.</div>
496
+ </form>
497
+
498
+ <!-- Forms are NOT created automatically, so you need to wrap the table in one to use features like bulk actions -->
499
+ <form id="movies-filter" method="get">
500
+ <!-- For plugins, we also need to ensure that the form posts back to our current page -->
501
+ <input type="hidden" name="page"
502
+ value="<?php echo filter_input( INPUT_GET, 'page', FILTER_SANITIZE_STRING ); ?>" />
503
+
504
+ <!-- Now we can render the completed list table -->
505
+ <?php $testListTable->display()?>
506
+ </form>
507
+
508
+ <?php add_thickbox(); ?>
509
+
510
+ </div>
511
+ <?php
512
+ }
513
+ }
Postman/Postman-Email-Log/PostmanEmailLogPostType.php CHANGED
@@ -1,51 +1,51 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
- if (! class_exists ( 'PostmanEmailLogPostType' )) {
6
-
7
- /**
8
- * This class creates the Custom Post Type for Email Logs and handles writing these posts.
9
- *
10
- * @author jasonhendriks
11
- */
12
- class PostmanEmailLogPostType {
13
-
14
- // constants
15
- const POSTMAN_CUSTOM_POST_TYPE_SLUG = 'postman_sent_mail';
16
-
17
- /**
18
- * Behavior to run on the WordPress 'init' action
19
- */
20
- public static function automaticallyCreatePostType() {
21
- add_action ( 'init', array (
22
- new PostmanEmailLogPostType (),
23
- 'create_post_type'
24
- ) );
25
- }
26
-
27
- /**
28
- * Create a custom post type
29
- * Callback function - must be public scope
30
- *
31
- * register_post_type should only be invoked through the 'init' action.
32
- * It will not work if called before 'init', and aspects of the newly
33
- * created or modified post type will work incorrectly if called later.
34
- *
35
- * https://codex.wordpress.org/Function_Reference/register_post_type
36
- */
37
- public static function create_post_type() {
38
- register_post_type ( self::POSTMAN_CUSTOM_POST_TYPE_SLUG, array (
39
- 'labels' => array (
40
- 'name' => _x ( 'Sent Emails', 'The group of Emails that have been delivered', 'post-smtp' ),
41
- 'singular_name' => _x ( 'Sent Email', 'An Email that has been delivered', 'post-smtp' )
42
- ),
43
- 'capability_type' => '',
44
- 'capabilities' => array ()
45
- ) );
46
- $logger = new PostmanLogger ( 'PostmanEmailLogPostType' );
47
- $logger->trace ( 'Created post type: ' . self::POSTMAN_CUSTOM_POST_TYPE_SLUG );
48
- }
49
- }
50
- }
51
-
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+ if (! class_exists ( 'PostmanEmailLogPostType' )) {
6
+
7
+ /**
8
+ * This class creates the Custom Post Type for Email Logs and handles writing these posts.
9
+ *
10
+ * @author jasonhendriks
11
+ */
12
+ class PostmanEmailLogPostType {
13
+
14
+ // constants
15
+ const POSTMAN_CUSTOM_POST_TYPE_SLUG = 'postman_sent_mail';
16
+
17
+ /**
18
+ * Behavior to run on the WordPress 'init' action
19
+ */
20
+ public static function automaticallyCreatePostType() {
21
+ add_action ( 'init', array (
22
+ new PostmanEmailLogPostType (),
23
+ 'create_post_type'
24
+ ) );
25
+ }
26
+
27
+ /**
28
+ * Create a custom post type
29
+ * Callback function - must be public scope
30
+ *
31
+ * register_post_type should only be invoked through the 'init' action.
32
+ * It will not work if called before 'init', and aspects of the newly
33
+ * created or modified post type will work incorrectly if called later.
34
+ *
35
+ * https://codex.wordpress.org/Function_Reference/register_post_type
36
+ */
37
+ public static function create_post_type() {
38
+ register_post_type ( self::POSTMAN_CUSTOM_POST_TYPE_SLUG, array (
39
+ 'labels' => array (
40
+ 'name' => _x ( 'Sent Emails', 'The group of Emails that have been delivered', 'post-smtp' ),
41
+ 'singular_name' => _x ( 'Sent Email', 'An Email that has been delivered', 'post-smtp' )
42
+ ),
43
+ 'capability_type' => '',
44
+ 'capabilities' => array ()
45
+ ) );
46
+ $logger = new PostmanLogger ( 'PostmanEmailLogPostType' );
47
+ $logger->trace ( 'Created post type: ' . self::POSTMAN_CUSTOM_POST_TYPE_SLUG );
48
+ }
49
+ }
50
+ }
51
+
Postman/Postman-Email-Log/PostmanEmailLogService.php CHANGED
@@ -1,340 +1,340 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- require_once dirname(__DIR__ ) . '/PostmanLogFields.php';
7
- require_once POST_SMTP_PATH . '/Postman/Extensions/Core/Notifications/PostmanNotify.php';
8
- require_once POST_SMTP_PATH . '/Postman/Extensions/Core/StatusSolution.php';
9
-
10
- if ( ! class_exists( 'PostmanEmailLog' ) ) {
11
- class PostmanEmailLog {
12
- public $sender;
13
- public $toRecipients;
14
- public $ccRecipients;
15
- public $bccRecipients;
16
- public $subject;
17
- public $body;
18
- public $success;
19
- public $statusMessage;
20
- public $sessionTranscript;
21
- public $transportUri;
22
- public $replyTo;
23
- public $originalTo;
24
- public $originalSubject;
25
- public $originalMessage;
26
- public $originalHeaders;
27
-
28
- public function setStatusMessage( $message ) {
29
- $this->statusMessage .= $message;
30
- }
31
- }
32
- }
33
-
34
- if ( ! class_exists( 'PostmanEmailLogService' ) ) {
35
-
36
- /**
37
- * This class creates the Custom Post Type for Email Logs and handles writing these posts.
38
- *
39
- * @author jasonhendriks
40
- */
41
- class PostmanEmailLogService {
42
-
43
- /*
44
- * Private content is published only for your eyes, or the eyes of only those with authorization
45
- * permission levels to see private content. Normal users and visitors will not be aware of
46
- * private content. It will not appear in the article lists. If a visitor were to guess the URL
47
- * for your private post, they would still not be able to see your content. You will only see
48
- * the private content when you are logged into your WordPress blog.
49
- */
50
- const POSTMAN_CUSTOM_POST_STATUS_PRIVATE = 'private';
51
-
52
- // member variables
53
- private $logger;
54
- private $inst;
55
-
56
- /**
57
- * Constructor
58
- */
59
- private function __construct() {
60
- $this->logger = new PostmanLogger( get_class( $this ) );
61
-
62
- add_action('post_smtp_on_success', array( $this, 'write_success_log' ), 10, 4 );
63
- add_action('post_smtp_on_failed', array( $this, 'write_failed_log' ), 10, 5 );
64
- }
65
-
66
- /**
67
- * singleton instance
68
- */
69
- public static function getInstance() {
70
- static $inst = null;
71
- if ( $inst === null ) {
72
- $inst = new PostmanEmailLogService();
73
- }
74
- return $inst;
75
- }
76
-
77
- public function write_success_log($log, $message, $transcript, $transport) {
78
- $options = PostmanOptions::getInstance();
79
- if ( $options->getRunMode() == PostmanOptions::RUN_MODE_PRODUCTION || $options->getRunMode() == PostmanOptions::RUN_MODE_LOG_ONLY ) {
80
- $this->writeSuccessLog( $log, $message, $transcript, $transport );
81
- }
82
- }
83
-
84
- public function write_failed_log($log, $message, $transcript, $transport, $statusMessage) {
85
- $options = PostmanOptions::getInstance();
86
- if ( $options->getRunMode() == PostmanOptions::RUN_MODE_PRODUCTION || $options->getRunMode() == PostmanOptions::RUN_MODE_LOG_ONLY ) {
87
- $this->writeFailureLog( $log, $message, $transcript, $transport, $statusMessage );
88
- }
89
- }
90
-
91
- /**
92
- * Logs successful email attempts
93
- *
94
- * @param PostmanMessage $message
95
- * @param mixed $transcript
96
- * @param PostmanModuleTransport $transport
97
- */
98
- public function writeSuccessLog( PostmanEmailLog $log, PostmanMessage $message, $transcript, PostmanModuleTransport $transport ) {
99
- if ( PostmanOptions::getInstance()->isMailLoggingEnabled() ) {
100
- $statusMessage = '';
101
- $status = true;
102
- $subject = $message->getSubject();
103
- if ( empty( $subject ) ) {
104
- $statusMessage = sprintf( '%s: %s', __( 'Warning', 'post-smtp' ), __( 'An empty subject line can result in delivery failure.', 'post-smtp' ) );
105
- $status = 'WARN';
106
- }
107
- $this->createLog( $log, $message, $transcript, $statusMessage, $status, $transport );
108
- $this->writeToEmailLog( $log );
109
- }
110
- }
111
-
112
- /**
113
- * Logs failed email attempts, requires more metadata so the email can be resent in the future
114
- *
115
- * @param PostmanMessage $message
116
- * @param mixed $transcript
117
- * @param PostmanModuleTransport $transport
118
- * @param mixed $statusMessage
119
- * @param mixed $originalTo
120
- * @param mixed $originalSubject
121
- * @param mixed $originalMessage
122
- * @param mixed $originalHeaders
123
- */
124
- public function writeFailureLog( PostmanEmailLog $log, PostmanMessage $message = null, $transcript, PostmanModuleTransport $transport, $statusMessage ) {
125
- if ( PostmanOptions::getInstance()->isMailLoggingEnabled() ) {
126
- $this->createLog( $log, $message, $transcript, $statusMessage, false, $transport );
127
- $this->writeToEmailLog( $log,$message );
128
- }
129
- }
130
-
131
- /**
132
- * Writes an email sending attempt to the Email Log
133
- *
134
- * From http://wordpress.stackexchange.com/questions/8569/wp-insert-post-php-function-and-custom-fields
135
- */
136
- private function writeToEmailLog( PostmanEmailLog $log, PostmanMessage $message = null ) {
137
-
138
- $options = PostmanOptions::getInstance();
139
-
140
- $new_status = $log->statusMessage;
141
-
142
- if ( $options->is_fallback && empty( $log->statusMessage ) ) {
143
- $new_status = 'Sent ( ** Fallback ** )';
144
- }
145
-
146
- if ( $options->is_fallback && ! empty( $log->statusMessage ) ) {
147
- $new_status = '( ** Fallback ** ) ' . $log->statusMessage;
148
- }
149
-
150
- $new_status = apply_filters( 'post_smtp_log_status', $new_status, $log, $message );
151
-
152
- // nothing here is sanitized as WordPress should take care of
153
- // making database writes safe
154
- $my_post = array(
155
- 'post_type' => PostmanEmailLogPostType::POSTMAN_CUSTOM_POST_TYPE_SLUG,
156
- 'post_title' => $log->subject,
157
- 'post_content' => $log->body,
158
- 'post_excerpt' => $new_status,
159
- 'post_status' => PostmanEmailLogService::POSTMAN_CUSTOM_POST_STATUS_PRIVATE,
160
- );
161
-
162
- // Insert the post into the database (WordPress gives us the Post ID)
163
- $post_id = wp_insert_post( $my_post, true );
164
-
165
- if ( is_wp_error( $post_id ) ) {
166
- add_action( 'admin_notices', function() use( $post_id ) {
167
- $class = 'notice notice-error';
168
- $message = $post_id->get_error_message();
169
-
170
- printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), esc_html( $message ) );
171
- });
172
-
173
- return;
174
- }
175
-
176
- $this->logger->debug( sprintf( 'Saved message #%s to the database', $post_id ) );
177
- $this->logger->trace( $log );
178
-
179
- $solution = apply_filters( 'post_smtp_log_solution', null, $new_status, $log, $message );
180
-
181
- // Write the meta data related to the email
182
- PostmanLogFields::get_instance()->update( $post_id, 'solution', $solution );
183
- PostmanLogFields::get_instance()->update( $post_id, 'success', $log->success );
184
- PostmanLogFields::get_instance()->update( $post_id, 'from_header', $log->sender );
185
- if ( ! empty( $log->toRecipients ) ) {
186
- PostmanLogFields::get_instance()->update( $post_id, 'to_header', $log->toRecipients );
187
- }
188
- if ( ! empty( $log->ccRecipients ) ) {
189
- PostmanLogFields::get_instance()->update( $post_id, 'cc_header', $log->ccRecipients );
190
- }
191
- if ( ! empty( $log->bccRecipients ) ) {
192
- PostmanLogFields::get_instance()->update( $post_id, 'bcc_header', $log->bccRecipients );
193
- }
194
- if ( ! empty( $log->replyTo ) ) {
195
- PostmanLogFields::get_instance()->update( $post_id, 'reply_to_header', $log->replyTo );
196
- }
197
- PostmanLogFields::get_instance()->update( $post_id, 'transport_uri', $log->transportUri );
198
-
199
- if ( ! $log->success || true ) {
200
- // alwas add the meta data so we can re-send it
201
- PostmanLogFields::get_instance()->update( $post_id, 'original_to', $log->originalTo );
202
- PostmanLogFields::get_instance()->update( $post_id, 'original_subject', $log->originalSubject );
203
- PostmanLogFields::get_instance()->update( $post_id, 'original_message', $log->originalMessage );
204
- PostmanLogFields::get_instance()->update( $post_id, 'original_headers', $log->originalHeaders );
205
- }
206
-
207
- // we do not sanitize the session transcript - let the reader decide how to handle the data
208
- PostmanLogFields::get_instance()->update( $post_id, 'session_transcript', $log->sessionTranscript );
209
-
210
- // truncate the log (remove older entries)
211
- $purger = new PostmanEmailLogPurger();
212
- $purger->truncateLogItems( PostmanOptions::getInstance()->getMailLoggingMaxEntries() );
213
- }
214
-
215
- /**
216
- * Creates a Log object for use by writeToEmailLog()
217
- *
218
- * @param PostmanMessage $message
219
- * @param mixed $transcript
220
- * @param mixed $statusMessage
221
- * @param mixed $success
222
- * @param PostmanModuleTransport $transport
223
- * @return PostmanEmailLog
224
- */
225
- private function createLog( PostmanEmailLog $log, PostmanMessage $message = null, $transcript, $statusMessage, $success, PostmanModuleTransport $transport ) {
226
- if ( $message ) {
227
- $log->sender = $message->getFromAddress()->format();
228
- $log->toRecipients = $this->flattenEmails( $message->getToRecipients() );
229
- $log->ccRecipients = $this->flattenEmails( $message->getCcRecipients() );
230
- $log->bccRecipients = $this->flattenEmails( $message->getBccRecipients() );
231
- $log->subject = $message->getSubject();
232
- $log->body = $message->getBody();
233
- if ( null !== $message->getReplyTo() ) {
234
- $log->replyTo = $message->getReplyTo()->format();
235
- }
236
- }
237
- $log->success = $success;
238
- $log->statusMessage = $statusMessage;
239
- $log->transportUri = PostmanTransportRegistry::getInstance()->getPublicTransportUri( $transport );
240
- $log->sessionTranscript = $log->transportUri . "\n\n" . $transcript;
241
- return $log;
242
- }
243
-
244
- /**
245
- * Creates a readable "TO" entry based on the recipient header
246
- *
247
- * @param array $addresses
248
- * @return string
249
- */
250
- private static function flattenEmails( array $addresses ) {
251
- $flat = '';
252
- $count = 0;
253
- foreach ( $addresses as $address ) {
254
- if ( $count >= 3 ) {
255
- $flat .= sprintf( __( '.. +%d more', 'post-smtp' ), sizeof( $addresses ) - $count );
256
- break;
257
- }
258
- if ( $count > 0 ) {
259
- $flat .= ', ';
260
- }
261
- $flat .= $address->format();
262
- $count ++;
263
- }
264
- return $flat;
265
- }
266
- }
267
- }
268
-
269
- if ( ! class_exists( 'PostmanEmailLogPurger' ) ) {
270
- class PostmanEmailLogPurger {
271
- private $posts;
272
- private $logger;
273
-
274
- /**
275
- *
276
- * @return mixed
277
- */
278
- function __construct( $args = array() ) {
279
- $this->logger = new PostmanLogger( get_class( $this ) );
280
- $defaults = array(
281
- 'posts_per_page' => -1,
282
- 'offset' => 0,
283
- 'category' => '',
284
- 'category_name' => '',
285
- 'orderby' => 'date',
286
- 'order' => 'DESC',
287
- 'include' => '',
288
- 'exclude' => '',
289
- 'meta_key' => '',
290
- 'meta_value' => '',
291
- 'post_type' => PostmanEmailLogPostType::POSTMAN_CUSTOM_POST_TYPE_SLUG,
292
- 'post_mime_type' => '',
293
- 'post_parent' => '',
294
- 'post_status' => 'private',
295
- 'suppress_filters' => true,
296
- );
297
- $args = wp_parse_args( $args, $defaults );
298
- $query = new WP_Query( $args );
299
- $this->posts = $query->posts;
300
- }
301
-
302
- /**
303
- *
304
- * @param array $posts
305
- * @param mixed $postid
306
- */
307
- function verifyLogItemExistsAndRemove( $postid ) {
308
- $force_delete = true;
309
- foreach ( $this->posts as $post ) {
310
- if ( $post->ID == $postid ) {
311
- $this->logger->debug( 'deleting log item ' . intval( $postid ) );
312
- wp_delete_post( $postid, $force_delete );
313
- return;
314
- }
315
- }
316
- $this->logger->warn( 'could not find Postman Log Item #' . $postid );
317
- }
318
- function removeAll() {
319
- $this->logger->debug( sprintf( 'deleting %d log items ', sizeof( $this->posts ) ) );
320
- $force_delete = true;
321
- foreach ( $this->posts as $post ) {
322
- wp_delete_post( $post->ID, $force_delete );
323
- }
324
- }
325
-
326
- /**
327
- *
328
- * @param mixed $size
329
- */
330
- function truncateLogItems( $size ) {
331
- $index = count( $this->posts );
332
- $force_delete = true;
333
- while ( $index > $size ) {
334
- $postid = $this->posts [ -- $index ]->ID;
335
- $this->logger->debug( 'deleting log item ' . $postid );
336
- wp_delete_post( $postid, $force_delete );
337
- }
338
- }
339
- }
340
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ require_once dirname(__DIR__ ) . '/PostmanLogFields.php';
7
+ require_once POST_SMTP_PATH . '/Postman/Extensions/Core/Notifications/PostmanNotify.php';
8
+ require_once POST_SMTP_PATH . '/Postman/Extensions/Core/StatusSolution.php';
9
+
10
+ if ( ! class_exists( 'PostmanEmailLog' ) ) {
11
+ class PostmanEmailLog {
12
+ public $sender;
13
+ public $toRecipients;
14
+ public $ccRecipients;
15
+ public $bccRecipients;
16
+ public $subject;
17
+ public $body;
18
+ public $success;
19
+ public $statusMessage;
20
+ public $sessionTranscript;
21
+ public $transportUri;
22
+ public $replyTo;
23
+ public $originalTo;
24
+ public $originalSubject;
25
+ public $originalMessage;
26
+ public $originalHeaders;
27
+
28
+ public function setStatusMessage( $message ) {
29
+ $this->statusMessage .= $message;
30
+ }
31
+ }
32
+ }
33
+
34
+ if ( ! class_exists( 'PostmanEmailLogService' ) ) {
35
+
36
+ /**
37
+ * This class creates the Custom Post Type for Email Logs and handles writing these posts.
38
+ *
39
+ * @author jasonhendriks
40
+ */
41
+ class PostmanEmailLogService {
42
+
43
+ /*
44
+ * Private content is published only for your eyes, or the eyes of only those with authorization
45
+ * permission levels to see private content. Normal users and visitors will not be aware of
46
+ * private content. It will not appear in the article lists. If a visitor were to guess the URL
47
+ * for your private post, they would still not be able to see your content. You will only see
48
+ * the private content when you are logged into your WordPress blog.
49
+ */
50
+ const POSTMAN_CUSTOM_POST_STATUS_PRIVATE = 'private';
51
+
52
+ // member variables
53
+ private $logger;
54
+ private $inst;
55
+
56
+ /**
57
+ * Constructor
58
+ */
59
+ private function __construct() {
60
+ $this->logger = new PostmanLogger( get_class( $this ) );
61
+
62
+ add_action('post_smtp_on_success', array( $this, 'write_success_log' ), 10, 4 );
63
+ add_action('post_smtp_on_failed', array( $this, 'write_failed_log' ), 10, 5 );
64
+ }
65
+
66
+ /**
67
+ * singleton instance
68
+ */
69
+ public static function getInstance() {
70
+ static $inst = null;
71
+ if ( $inst === null ) {
72
+ $inst = new PostmanEmailLogService();
73
+ }
74
+ return $inst;
75
+ }
76
+
77
+ public function write_success_log($log, $message, $transcript, $transport) {
78
+ $options = PostmanOptions::getInstance();
79
+ if ( $options->getRunMode() == PostmanOptions::RUN_MODE_PRODUCTION || $options->getRunMode() == PostmanOptions::RUN_MODE_LOG_ONLY ) {
80
+ $this->writeSuccessLog( $log, $message, $transcript, $transport );
81
+ }
82
+ }
83
+
84
+ public function write_failed_log($log, $message, $transcript, $transport, $statusMessage) {
85
+ $options = PostmanOptions::getInstance();
86
+ if ( $options->getRunMode() == PostmanOptions::RUN_MODE_PRODUCTION || $options->getRunMode() == PostmanOptions::RUN_MODE_LOG_ONLY ) {
87
+ $this->writeFailureLog( $log, $message, $transcript, $transport, $statusMessage );
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Logs successful email attempts
93
+ *
94
+ * @param PostmanMessage $message
95
+ * @param mixed $transcript
96
+ * @param PostmanModuleTransport $transport
97
+ */
98
+ public function writeSuccessLog( PostmanEmailLog $log, PostmanMessage $message, $transcript, PostmanModuleTransport $transport ) {
99
+ if ( PostmanOptions::getInstance()->isMailLoggingEnabled() ) {
100
+ $statusMessage = '';
101
+ $status = true;
102
+ $subject = $message->getSubject();
103
+ if ( empty( $subject ) ) {
104
+ $statusMessage = sprintf( '%s: %s', __( 'Warning', 'post-smtp' ), __( 'An empty subject line can result in delivery failure.', 'post-smtp' ) );
105
+ $status = 'WARN';
106
+ }
107
+ $this->createLog( $log, $message, $transcript, $statusMessage, $status, $transport );
108
+ $this->writeToEmailLog( $log );
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Logs failed email attempts, requires more metadata so the email can be resent in the future
114
+ *
115
+ * @param PostmanMessage $message
116
+ * @param mixed $transcript
117
+ * @param PostmanModuleTransport $transport
118
+ * @param mixed $statusMessage
119
+ * @param mixed $originalTo
120
+ * @param mixed $originalSubject
121
+ * @param mixed $originalMessage
122
+ * @param mixed $originalHeaders
123
+ */
124
+ public function writeFailureLog( PostmanEmailLog $log, PostmanMessage $message = null, $transcript, PostmanModuleTransport $transport, $statusMessage ) {
125
+ if ( PostmanOptions::getInstance()->isMailLoggingEnabled() ) {
126
+ $this->createLog( $log, $message, $transcript, $statusMessage, false, $transport );
127
+ $this->writeToEmailLog( $log,$message );
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Writes an email sending attempt to the Email Log
133
+ *
134
+ * From http://wordpress.stackexchange.com/questions/8569/wp-insert-post-php-function-and-custom-fields
135
+ */
136
+ private function writeToEmailLog( PostmanEmailLog $log, PostmanMessage $message = null ) {
137
+
138
+ $options = PostmanOptions::getInstance();
139
+
140
+ $new_status = $log->statusMessage;
141
+
142
+ if ( $options->is_fallback && empty( $log->statusMessage ) ) {
143
+ $new_status = 'Sent ( ** Fallback ** )';
144
+ }
145
+
146
+ if ( $options->is_fallback && ! empty( $log->statusMessage ) ) {
147
+ $new_status = '( ** Fallback ** ) ' . $log->statusMessage;
148
+ }
149
+
150
+ $new_status = apply_filters( 'post_smtp_log_status', $new_status, $log, $message );
151
+
152
+ // nothing here is sanitized as WordPress should take care of
153
+ // making database writes safe
154
+ $my_post = array(
155
+ 'post_type' => PostmanEmailLogPostType::POSTMAN_CUSTOM_POST_TYPE_SLUG,
156
+ 'post_title' => $log->subject,
157
+ 'post_content' => $log->body,
158
+ 'post_excerpt' => $new_status,
159
+ 'post_status' => PostmanEmailLogService::POSTMAN_CUSTOM_POST_STATUS_PRIVATE,
160
+ );
161
+
162
+ // Insert the post into the database (WordPress gives us the Post ID)
163
+ $post_id = wp_insert_post( $my_post, true );
164
+
165
+ if ( is_wp_error( $post_id ) ) {
166
+ add_action( 'admin_notices', function() use( $post_id ) {
167
+ $class = 'notice notice-error';
168
+ $message = $post_id->get_error_message();
169
+
170
+ printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), esc_html( $message ) );
171
+ });
172
+
173
+ return;
174
+ }
175
+
176
+ $this->logger->debug( sprintf( 'Saved message #%s to the database', $post_id ) );
177
+ $this->logger->trace( $log );
178
+
179
+ $solution = apply_filters( 'post_smtp_log_solution', null, $new_status, $log, $message );
180
+
181
+ // Write the meta data related to the email
182
+ PostmanLogFields::get_instance()->update( $post_id, 'solution', $solution );
183
+ PostmanLogFields::get_instance()->update( $post_id, 'success', $log->success );
184
+ PostmanLogFields::get_instance()->update( $post_id, 'from_header', $log->sender );
185
+ if ( ! empty( $log->toRecipients ) ) {
186
+ PostmanLogFields::get_instance()->update( $post_id, 'to_header', $log->toRecipients );
187
+ }
188
+ if ( ! empty( $log->ccRecipients ) ) {
189
+ PostmanLogFields::get_instance()->update( $post_id, 'cc_header', $log->ccRecipients );
190
+ }
191
+ if ( ! empty( $log->bccRecipients ) ) {
192
+ PostmanLogFields::get_instance()->update( $post_id, 'bcc_header', $log->bccRecipients );
193
+ }
194
+ if ( ! empty( $log->replyTo ) ) {
195
+ PostmanLogFields::get_instance()->update( $post_id, 'reply_to_header', $log->replyTo );
196
+ }
197
+ PostmanLogFields::get_instance()->update( $post_id, 'transport_uri', $log->transportUri );
198
+
199
+ if ( ! $log->success || true ) {
200
+ // alwas add the meta data so we can re-send it
201
+ PostmanLogFields::get_instance()->update( $post_id, 'original_to', $log->originalTo );
202
+ PostmanLogFields::get_instance()->update( $post_id, 'original_subject', $log->originalSubject );
203
+ PostmanLogFields::get_instance()->update( $post_id, 'original_message', $log->originalMessage );
204
+ PostmanLogFields::get_instance()->update( $post_id, 'original_headers', $log->originalHeaders );
205
+ }
206
+
207
+ // we do not sanitize the session transcript - let the reader decide how to handle the data
208
+ PostmanLogFields::get_instance()->update( $post_id, 'session_transcript', $log->sessionTranscript );
209
+
210
+ // truncate the log (remove older entries)
211
+ $purger = new PostmanEmailLogPurger();
212
+ $purger->truncateLogItems( PostmanOptions::getInstance()->getMailLoggingMaxEntries() );
213
+ }
214
+
215
+ /**
216
+ * Creates a Log object for use by writeToEmailLog()
217
+ *
218
+ * @param PostmanMessage $message
219
+ * @param mixed $transcript
220
+ * @param mixed $statusMessage
221
+ * @param mixed $success
222
+ * @param PostmanModuleTransport $transport
223
+ * @return PostmanEmailLog
224
+ */
225
+ private function createLog( PostmanEmailLog $log, PostmanMessage $message = null, $transcript, $statusMessage, $success, PostmanModuleTransport $transport ) {
226
+ if ( $message ) {
227
+ $log->sender = $message->getFromAddress()->format();
228
+ $log->toRecipients = $this->flattenEmails( $message->getToRecipients() );
229
+ $log->ccRecipients = $this->flattenEmails( $message->getCcRecipients() );
230
+ $log->bccRecipients = $this->flattenEmails( $message->getBccRecipients() );
231
+ $log->subject = $message->getSubject();
232
+ $log->body = $message->getBody();
233
+ if ( null !== $message->getReplyTo() ) {
234
+ $log->replyTo = $message->getReplyTo()->format();
235
+ }
236
+ }
237
+ $log->success = $success;
238
+ $log->statusMessage = $statusMessage;
239
+ $log->transportUri = PostmanTransportRegistry::getInstance()->getPublicTransportUri( $transport );
240
+ $log->sessionTranscript = $log->transportUri . "\n\n" . $transcript;
241
+ return $log;
242
+ }
243
+
244
+ /**
245
+ * Creates a readable "TO" entry based on the recipient header
246
+ *
247
+ * @param array $addresses
248
+ * @return string
249
+ */
250
+ private static function flattenEmails( array $addresses ) {
251
+ $flat = '';
252
+ $count = 0;
253
+ foreach ( $addresses as $address ) {
254
+ if ( $count >= 3 ) {
255
+ $flat .= sprintf( __( '.. +%d more', 'post-smtp' ), sizeof( $addresses ) - $count );
256
+ break;
257
+ }
258
+ if ( $count > 0 ) {
259
+ $flat .= ', ';
260
+ }
261
+ $flat .= $address->format();
262
+ $count ++;
263
+ }
264
+ return $flat;
265
+ }
266
+ }
267
+ }
268
+
269
+ if ( ! class_exists( 'PostmanEmailLogPurger' ) ) {
270
+ class PostmanEmailLogPurger {
271
+ private $posts;
272
+ private $logger;
273
+
274
+ /**
275
+ *
276
+ * @return mixed
277
+ */
278
+ function __construct( $args = array() ) {
279
+ $this->logger = new PostmanLogger( get_class( $this ) );
280
+ $defaults = array(
281
+ 'posts_per_page' => -1,
282
+ 'offset' => 0,
283
+ 'category' => '',
284
+ 'category_name' => '',
285
+ 'orderby' => 'date',
286
+ 'order' => 'DESC',
287
+ 'include' => '',
288
+ 'exclude' => '',
289
+ 'meta_key' => '',
290
+ 'meta_value' => '',
291
+ 'post_type' => PostmanEmailLogPostType::POSTMAN_CUSTOM_POST_TYPE_SLUG,
292
+ 'post_mime_type' => '',
293
+ 'post_parent' => '',
294
+ 'post_status' => 'private',
295
+ 'suppress_filters' => true,
296
+ );
297
+ $args = wp_parse_args( $args, $defaults );
298
+ $query = new WP_Query( $args );
299
+ $this->posts = $query->posts;
300
+ }
301
+
302
+ /**
303
+ *
304
+ * @param array $posts
305
+ * @param mixed $postid
306
+ */
307
+ function verifyLogItemExistsAndRemove( $postid ) {
308
+ $force_delete = true;
309
+ foreach ( $this->posts as $post ) {
310
+ if ( $post->ID == $postid ) {
311
+ $this->logger->debug( 'deleting log item ' . intval( $postid ) );
312
+ wp_delete_post( $postid, $force_delete );
313
+ return;
314
+ }
315
+ }
316
+ $this->logger->warn( 'could not find Postman Log Item #' . $postid );
317
+ }
318
+ function removeAll() {
319
+ $this->logger->debug( sprintf( 'deleting %d log items ', sizeof( $this->posts ) ) );
320
+ $force_delete = true;
321
+ foreach ( $this->posts as $post ) {
322
+ wp_delete_post( $post->ID, $force_delete );
323
+ }
324
+ }
325
+
326
+ /**
327
+ *
328
+ * @param mixed $size
329
+ */
330
+ function truncateLogItems( $size ) {
331
+ $index = count( $this->posts );
332
+ $force_delete = true;
333
+ while ( $index > $size ) {
334
+ $postid = $this->posts [ -- $index ]->ID;
335
+ $this->logger->debug( 'deleting log item ' . $postid );
336
+ wp_delete_post( $postid, $force_delete );
337
+ }
338
+ }
339
+ }
340
+ }
Postman/Postman-Email-Log/PostmanEmailLogView.php CHANGED
@@ -1,454 +1,454 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
- require_once dirname(__DIR__) . '/PostmanLogFields.php';
6
-
7
- /**
8
- * See http://wpengineer.com/2426/wp_list_table-a-step-by-step-guide/
9
- */
10
- if ( ! class_exists( 'WP_List_Table' ) ) {
11
- require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
12
- }
13
- class PostmanEmailLogView extends WP_List_Table {
14
- private $logger;
15
-
16
- /**
17
- * ************************************************************************
18
- * REQUIRED.
19
- * Set up a constructor that references the parent constructor. We
20
- * use the parent reference to set some default configs.
21
- * *************************************************************************
22
- */
23
- function __construct() {
24
- $this->logger = new PostmanLogger( get_class( $this ) );
25
-
26
- // Set parent defaults
27
- parent::__construct( array(
28
- 'singular' => 'email_log_entry', // singular name of the listed records
29
- 'plural' => 'email_log_entries', // plural name of the listed records
30
- 'ajax' => false,
31
- ) ); // does this table support ajax?
32
- }
33
-
34
- /**
35
- * ************************************************************************
36
- * Recommended.
37
- * This method is called when the parent class can't find a method
38
- * specifically build for a given column. Generally, it's recommended to include
39
- * one method for each column you want to render, keeping your package class
40
- * neat and organized. For example, if the class needs to process a column
41
- * named 'title', it would first see if a method named $this->column_title()
42
- * exists - if it does, that method will be used. If it doesn't, this one will
43
- * be used. Generally, you should try to use custom column methods as much as
44
- * possible.
45
- *
46
- * Since we have defined a column_title() method later on, this method doesn't
47
- * need to concern itself with any column with a name of 'title'. Instead, it
48
- * needs to handle everything else.
49
- *
50
- * For more detailed insight into how columns are handled, take a look at
51
- * WP_List_Table::single_row_columns()
52
- *
53
- * @param array $item
54
- * A singular item (one full row's worth of data)
55
- * @param array $column_name
56
- * The name/slug of the column to be processed
57
- * @return string Text or HTML to be placed inside the column <td>
58
- * ************************************************************************
59
- */
60
- function column_default( $item, $column_name ) {
61
- switch ( $column_name ) {
62
- case 'sent_to' :
63
- case 'solution' :
64
- case 'date' :
65
- case 'status' :
66
- return $item [ $column_name ];
67
- default :
68
- return print_r( $item, true ); // Show the whole array for troubleshooting purposes
69
- }
70
- }
71
-
72
- /**
73
- * ************************************************************************
74
- * Recommended.
75
- * This is a custom column method and is responsible for what
76
- * is rendered in any column with a name/slug of 'title'. Every time the class
77
- * needs to render a column, it first looks for a method named
78
- * column_{$column_title} - if it exists, that method is run. If it doesn't
79
- * exist, column_default() is called instead.
80
- *
81
- * This example also illustrates how to implement rollover actions. Actions
82
- * should be an associative array formatted as 'slug'=>'link html' - and you
83
- * will need to generate the URLs yourself. You could even ensure the links
84
- *
85
- * @see WP_List_Table::::single_row_columns()
86
- * @param array $item
87
- * A singular item (one full row's worth of data)
88
- * @return string Text to be placed inside the column <td> (movie title only)
89
- * ************************************************************************
90
- */
91
- function column_title( $item ) {
92
-
93
- // Build row actions
94
- $iframeUri = 'admin-post.php?page=postman_email_log&action=%s&email=%s&TB_iframe=true&width=700&height=550';
95
- $deleteUrl = wp_nonce_url( admin_url( sprintf( 'admin-post.php?page=postman_email_log&action=%s&email=%s', 'delete', $item ['ID'] ) ), 'delete_email_log_item_' . $item ['ID'] );
96
- $viewUrl = admin_url( sprintf( $iframeUri, 'view', $item ['ID'] ) );
97
- $transcriptUrl = admin_url( sprintf( $iframeUri, 'transcript', $item ['ID'] ) );
98
- $resendUrl = admin_url( sprintf( $iframeUri, 'resend', $item ['ID'] ) );
99
-
100
- $meta_values = PostmanLogFields::get_instance()->get( $item ['ID'] );
101
-
102
- $actions = array(
103
- 'delete' => sprintf( '<a href="%s">%s</a>', $deleteUrl, _x( 'Delete', 'Delete an item from the email log', 'post-smtp' ) ),
104
- 'view' => sprintf( '<a href="%s" class="thickbox">%s</a>', $viewUrl, _x( 'View', 'View an item from the email log', 'post-smtp' ) ),
105
- );
106
-
107
- if ( ! empty( $meta_values ['session_transcript'] [0] ) ) {
108
- $actions ['transcript'] = sprintf( '<a href="%1$s" class="thickbox">%2$s</a>', $transcriptUrl, __( 'Session Transcript', 'post-smtp' ) );
109
- } else {
110
- $actions ['transcript'] = sprintf( '%2$s', $transcriptUrl, __( 'Session Transcript', 'post-smtp' ) );
111
- }
112
- if ( ! (empty( $meta_values ['original_to'] [0] ) && empty( $meta_values ['originalHeaders'] [0] )) ) {
113
- // $actions ['resend'] = sprintf ( '<a href="%s">%s</a>', $resendUrl, __ ( 'Resend', 'post-smtp' ) );
114
- $emails = $meta_values ['original_to'] [0];
115
- $to = !is_array( $emails ) ? explode( ',', $emails ) : $emails;
116
- $to = array_map( 'sanitize_email', $to );
117
- $to = implode( ',', $to );
118
-
119
- $actions ['resend'] = sprintf( '<span id="%3$s"><a class="postman-open-resend" href="#">%2$s</a></span><div style="display:none;"><input type="hidden" name="security" value="%6$s"><input type="text" name="mail_to" class="regular-text ltr" data-id="%1$s" value="%4$s"><button class="postman-resend button button-primary">%2$s</button><i style="color: black;">%5$s</i></div>', $item ['ID'], __( 'Resend', 'post-smtp' ), 'resend-' . $item ['ID'], esc_attr( $to ), __( 'comma-separated for multiple emails', 'post-smtp' ), wp_create_nonce( 'resend' ) );
120
- } else {
121
- $actions ['resend'] = sprintf( '%2$s', $resendUrl, __( 'Resend', 'post-smtp' ) );
122
- }
123
-
124
- // Return the title contents
125
- return sprintf( '%1$s %3$s',
126
- /*$1%s*/ $item ['title'],
127
- /*$2%s*/ $item ['ID'],
128
- /*$3%s*/ $this->row_actions( $actions ) );
129
- }
130
-
131
- /**
132
- * ************************************************************************
133
- * REQUIRED if displaying checkboxes or using bulk actions! The 'cb' column
134
- * is given special treatment when columns are processed.
135
- * It ALWAYS needs to
136
- * have it's own method.
137
- *
138
- * @see WP_List_Table::::single_row_columns()
139
- * @param array $item
140
- * A singular item (one full row's worth of data)
141
- * @return string Text to be placed inside the column <td> (movie title only)
142
- * ************************************************************************
143
- */
144
- function column_cb( $item ) {
145
- return sprintf( '<input type="checkbox" name="%1$s[]" value="%2$s" />',
146
- /*$1%s*/ $this->_args ['singular'], // Let's simply repurpose the table's singular label ("movie")
147
- /* $2%s */
148
- $item ['ID'] ); // The value of the checkbox should be the record's id
149
- }
150
-
151
- /**
152
- * ************************************************************************
153
- * REQUIRED! This method dictates the table's columns and titles.
154
- * This should
155
- * return an array where the key is the column slug (and class) and the value
156
- * is the column's title text. If you need a checkbox for bulk actions, refer
157
- * to the $columns array below.
158
- *
159
- * The 'cb' column is treated differently than the rest. If including a checkbox
160
- * column in your table you must create a column_cb() method. If you don't need
161
- * bulk actions or checkboxes, simply leave the 'cb' entry out of your array.
162
- *
163
- * @see WP_List_Table::::single_row_columns()
164
- * @return array An associative array containing column information: 'slugs'=>'Visible Titles'
165
- * ************************************************************************
166
- */
167
- function get_columns() {
168
- $columns = array(
169
- 'cb' => '<input type="checkbox" />', // Render a checkbox instead of text
170
- 'title' => _x( 'Subject', 'What is the subject of this message?', 'post-smtp' ),
171
- 'sent_to' => __( 'Sent To', 'post-smtp' ),
172
- 'status' => __( 'Status', 'post-smtp' ),
173
- 'solution' => __( 'Solution', 'post-smtp' ),
174
- 'date' => _x( 'Delivery Time', 'When was this email sent?', 'post-smtp' ),
175
- );
176
- return $columns;
177
- }
178
-
179
- /**
180
- * ************************************************************************
181
- * Optional.
182
- * If you want one or more columns to be sortable (ASC/DESC toggle),
183
- * you will need to register it here. This should return an array where the
184
- * key is the column that needs to be sortable, and the value is db column to
185
- * sort by. Often, the key and value will be the same, but this is not always
186
- * the case (as the value is a column name from the database, not the list table).
187
- *
188
- * This method merely defines which columns should be sortable and makes them
189
- * clickable - it does not handle the actual sorting. You still need to detect
190
- * the ORDERBY and ORDER querystring variables within prepare_items() and sort
191
- * your data accordingly (usually by modifying your query).
192
- *
193
- * @return array An associative array containing all the columns that should be sortable: 'slugs'=>array('data_values',bool)
194
- * ************************************************************************
195
- */
196
- function get_sortable_columns() {
197
- return array();
198
- $sortable_columns = array(
199
- 'title' => array(
200
- 'title',
201
- false,
202
- ), // true means it's already sorted
203
- 'status' => array(
204
- 'status',
205
- false,
206
- ),
207
- 'date' => array(
208
- 'date',
209
- false,
210
- ),
211
- );
212
- return $sortable_columns;
213
- }
214
-
215
- /**
216
- * ************************************************************************
217
- * Optional.
218
- * If you need to include bulk actions in your list table, this is
219
- * the place to define them. Bulk actions are an associative array in the format
220
- * 'slug'=>'Visible Title'
221
- *
222
- * If this method returns an empty value, no bulk action will be rendered. If
223
- * you specify any bulk actions, the bulk actions box will be rendered with
224
- * the table automatically on display().
225
- *
226
- * Also note that list tables are not automatically wrapped in <form> elements,
227
- * so you will need to create those manually in order for bulk actions to function.
228
- *
229
- * @return array An associative array containing all the bulk actions: 'slugs'=>'Visible Titles'
230
- * ************************************************************************
231
- */
232
- function get_bulk_actions() {
233
- $actions = array(
234
- 'bulk_delete' => _x( 'Delete', 'Delete an item from the email log', 'post-smtp' ),
235
- );
236
- return $actions;
237
- }
238
-
239
- /**
240
- * ************************************************************************
241
- * Optional.
242
- * You can handle your bulk actions anywhere or anyhow you prefer.
243
- * For this example package, we will handle it in the class to keep things
244
- * clean and organized.
245
- *
246
- * @see $this->prepare_items() ************************************************************************
247
- */
248
- function process_bulk_action() {
249
- }
250
-
251
- /**
252
- * ************************************************************************
253
- * REQUIRED! This is where you prepare your data for display.
254
- * This method will
255
- * usually be used to query the database, sort and filter the data, and generally
256
- * get it ready to be displayed. At a minimum, we should set $this->items and
257
- * $this->set_pagination_args(), although the following properties and methods
258
- * are frequently interacted with here...
259
- *
260
- * @global WPDB $wpdb
261
- * @uses $this->_column_headers
262
- * @uses $this->items
263
- * @uses $this->get_columns()
264
- * @uses $this->get_sortable_columns()
265
- * @uses $this->get_pagenum()
266
- * @uses $this->set_pagination_args()
267
- * ************************************************************************
268
- */
269
- function prepare_items() {
270
-
271
- if ( ! current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_LOGS ) ) {
272
- wp_die( sprintf( 'You need to add to this user the %s capability. You can try disable and enable the plugin or you can do it with a plugin like `user role editor`.', Postman::MANAGE_POSTMAN_CAPABILITY_LOGS ) );
273
- }
274
-
275
- /**
276
- * First, lets decide how many records per page to show
277
- */
278
- $per_page = isset( $_GET['postman_page_records'] ) ? absint( $_GET['postman_page_records'] ) : 10;
279
-
280
- /**
281
- * REQUIRED.
282
- * Now we need to define our column headers. This includes a complete
283
- * array of columns to be displayed (slugs & titles), a list of columns
284
- * to keep hidden, and a list of columns that are sortable. Each of these
285
- * can be defined in another method (as we've done here) before being
286
- * used to build the value for our _column_headers property.
287
- */
288
- $columns = $this->get_columns();
289
- $hidden = array();
290
- $sortable = $this->get_sortable_columns();
291
-
292
- /**
293
- * REQUIRED.
294
- * Finally, we build an array to be used by the class for column
295
- * headers. The $this->_column_headers property takes an array which contains
296
- * 3 other arrays. One for all columns, one for hidden columns, and one
297
- * for sortable columns.
298
- */
299
- $this->_column_headers = array(
300
- $columns,
301
- $hidden,
302
- $sortable,
303
- );
304
-
305
- /**
306
- * Optional.
307
- * You can handle your bulk actions however you see fit. In this
308
- * case, we'll handle them within our package just to keep things clean.
309
- */
310
- $this->process_bulk_action();
311
-
312
- /**
313
- * Instead of querying a database, we're going to fetch the example data
314
- * property we created for use in this plugin.
315
- * This makes this example
316
- * package slightly different than one you might build on your own. In
317
- * this example, we'll be using array manipulation to sort and paginate
318
- * our data. In a real-world implementation, you will probably want to
319
- * use sort and pagination data to build a custom query instead, as you'll
320
- * be able to use your precisely-queried data immediately.
321
- */
322
- $data = array();
323
-
324
- $args = array(
325
- 'posts_per_page' => -1,
326
- 'orderby' => 'date',
327
- 'order' => 'DESC',
328
- 'post_type' => PostmanEmailLogPostType::POSTMAN_CUSTOM_POST_TYPE_SLUG,
329
- 'post_status' => 'private',
330
- 'suppress_filters' => true,
331
- );
332
-
333
- if ( isset( $_GET['from_date'] ) && ! empty( $_GET['from_date'] ) ) {
334
- $from_date = sanitize_text_field( $_GET['from_date'] );
335
-
336
- $args['date_query']['after'] = $from_date;
337
- $args['date_query']['column'] = 'post_date';
338
- $args['date_query']['inclusive'] = false;
339
- }
340
-
341
- if ( isset( $_GET['to_date'] ) && ! empty( $_GET['to_date'] ) ) {
342
- $to_date = sanitize_text_field( $_GET['to_date'] );
343
-
344
- $args['date_query']['before'] = $to_date;
345
- $args['date_query']['column'] = 'post_date';
346
- $args['date_query']['inclusive'] = true;
347
- }
348
-
349
- if ( ! empty( $_GET['search'] ) ) {
350
-
351
- if ( isset( $args['date_query'] ) ) {
352
- unset( $args['date_query'] ); }
353
-
354
- $args['s'] = sanitize_text_field( $_GET['search'] );
355
- }
356
-
357
- if ( isset( $_GET['postman_trash_all'] ) ) {
358
- $args['posts_per_page'] = -1;
359
- }
360
- $posts = new WP_query( $args );
361
-
362
- $date_format = get_option( 'date_format' );
363
- $time_format = get_option( 'time_format' );
364
-
365
- foreach ( $posts->posts as $post ) {
366
- $date = $post->post_date;
367
- $humanTime = human_time_diff( strtotime( $post->post_date_gmt ) );
368
- // if this PHP system support humanTime, than use it
369
- if ( ! empty( $humanTime ) ) {
370
- /* Translators: where %s indicates the relative time from now */
371
- $date = sprintf( _x( '%s ago', 'A relative time as in "five days ago"', 'post-smtp' ), $humanTime );
372
- }
373
- $meta_values = PostmanLogFields::get_instance()->get( $post->ID );
374
- $sent_to = array_map( 'esc_html', explode( ',' , $meta_values ['to_header'] [0] ) );
375
- $solution_meta = $meta_values ['solution'] [0];
376
-
377
- if ( empty( $solution_meta ) && empty( $post->post_excerpt ) ) {
378
- $solution = 'No need - Mail sent';
379
- } else {
380
- $solution = $solution_meta;
381
- }
382
-
383
- $flattenedPost = array(
384
- // the post title must be escaped as they are displayed in the HTML output
385
- 'sent_to' => implode( ', ', $sent_to ),
386
- 'title' => esc_html( $post->post_title ),
387
- 'solution' => $solution,
388
- // the post status must be escaped as they are displayed in the HTML output
389
- 'status' => ($post->post_excerpt != null ? esc_html( $post->post_excerpt ) : __( 'Sent', 'post-smtp' )),
390
- 'date' => date( "$date_format $time_format", strtotime( $post->post_date ) ),
391
- 'ID' => $post->ID,
392
- );
393
- array_push( $data, $flattenedPost );
394
- }
395
-
396
- /**
397
- * *********************************************************************
398
- * ---------------------------------------------------------------------
399
- * vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
400
- *
401
- * In a real-world situation, this is where you would place your query.
402
- *
403
- * For information on making queries in WordPress, see this Codex entry:
404
- * http://codex.wordpress.org/Class_Reference/wpdb
405
- *
406
- * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
407
- * ---------------------------------------------------------------------
408
- * ********************************************************************
409
- */
410
-
411
- /**
412
- * REQUIRED for pagination.
413
- * Let's figure out what page the user is currently
414
- * looking at. We'll need this later, so you should always include it in
415
- * your own package classes.
416
- */
417
- $current_page = $this->get_pagenum();
418
-
419
- /**
420
- * REQUIRED for pagination.
421
- * Let's check how many items are in our data array.
422
- * In real-world use, this would be the total number of items in your database,
423
- * without filtering. We'll need this later, so you should always include it
424
- * in your own package classes.
425
- */
426
- $total_items = count( $data );
427
-
428
- /**
429
- * The WP_List_Table class does not handle pagination for us, so we need
430
- * to ensure that the data is trimmed to only the current page.
431
- * We can use
432
- * array_slice() to
433
- */
434
- $data = array_slice( $data, (($current_page - 1) * $per_page), $per_page );
435
-
436
- /**
437
- * REQUIRED.
438
- * Now we can add our *sorted* data to the items property, where
439
- * it can be used by the rest of the class.
440
- */
441
- $this->items = $data;
442
-
443
- /**
444
- * REQUIRED.
445
- * We also have to register our pagination options & calculations.
446
- */
447
- $this->set_pagination_args( array(
448
- 'total_items' => $total_items, // WE have to calculate the total number of items
449
- 'per_page' => $per_page, // WE have to determine how many items to show on a page
450
- 'total_pages' => ceil( $total_items / $per_page ),
451
- ) ); // WE have to calculate the total number of pages
452
- }
453
- }
454
-
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+ require_once dirname(__DIR__) . '/PostmanLogFields.php';
6
+
7
+ /**
8
+ * See http://wpengineer.com/2426/wp_list_table-a-step-by-step-guide/
9
+ */
10
+ if ( ! class_exists( 'WP_List_Table' ) ) {
11
+ require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
12
+ }
13
+ class PostmanEmailLogView extends WP_List_Table {
14
+ private $logger;
15
+
16
+ /**
17
+ * ************************************************************************
18
+ * REQUIRED.
19
+ * Set up a constructor that references the parent constructor. We
20
+ * use the parent reference to set some default configs.
21
+ * *************************************************************************
22
+ */
23
+ function __construct() {
24
+ $this->logger = new PostmanLogger( get_class( $this ) );
25
+
26
+ // Set parent defaults
27
+ parent::__construct( array(
28
+ 'singular' => 'email_log_entry', // singular name of the listed records
29
+ 'plural' => 'email_log_entries', // plural name of the listed records
30
+ 'ajax' => false,
31
+ ) ); // does this table support ajax?
32
+ }
33
+
34
+ /**
35
+ * ************************************************************************
36
+ * Recommended.
37
+ * This method is called when the parent class can't find a method
38
+ * specifically build for a given column. Generally, it's recommended to include
39
+ * one method for each column you want to render, keeping your package class
40
+ * neat and organized. For example, if the class needs to process a column
41
+ * named 'title', it would first see if a method named $this->column_title()
42
+ * exists - if it does, that method will be used. If it doesn't, this one will
43
+ * be used. Generally, you should try to use custom column methods as much as
44
+ * possible.
45
+ *
46
+ * Since we have defined a column_title() method later on, this method doesn't
47
+ * need to concern itself with any column with a name of 'title'. Instead, it
48
+ * needs to handle everything else.
49
+ *
50
+ * For more detailed insight into how columns are handled, take a look at
51
+ * WP_List_Table::single_row_columns()
52
+ *
53
+ * @param array $item
54
+ * A singular item (one full row's worth of data)
55
+ * @param array $column_name
56
+ * The name/slug of the column to be processed
57
+ * @return string Text or HTML to be placed inside the column <td>
58
+ * ************************************************************************
59
+ */
60
+ function column_default( $item, $column_name ) {
61
+ switch ( $column_name ) {
62
+ case 'sent_to' :
63
+ case 'solution' :
64
+ case 'date' :
65
+ case 'status' :
66
+ return $item [ $column_name ];
67
+ default :
68
+ return print_r( $item, true ); // Show the whole array for troubleshooting purposes
69
+ }
70
+ }
71
+
72
+ /**
73
+ * ************************************************************************
74
+ * Recommended.
75
+ * This is a custom column method and is responsible for what
76
+ * is rendered in any column with a name/slug of 'title'. Every time the class
77
+ * needs to render a column, it first looks for a method named
78
+ * column_{$column_title} - if it exists, that method is run. If it doesn't
79
+ * exist, column_default() is called instead.
80
+ *
81
+ * This example also illustrates how to implement rollover actions. Actions
82
+ * should be an associative array formatted as 'slug'=>'link html' - and you
83
+ * will need to generate the URLs yourself. You could even ensure the links
84
+ *
85
+ * @see WP_List_Table::::single_row_columns()
86
+ * @param array $item
87
+ * A singular item (one full row's worth of data)
88
+ * @return string Text to be placed inside the column <td> (movie title only)
89
+ * ************************************************************************
90
+ */
91
+ function column_title( $item ) {
92
+
93
+ // Build row actions
94
+ $iframeUri = 'admin-post.php?page=postman_email_log&action=%s&email=%s&TB_iframe=true&width=700&height=550';
95
+ $deleteUrl = wp_nonce_url( admin_url( sprintf( 'admin-post.php?page=postman_email_log&action=%s&email=%s', 'delete', $item ['ID'] ) ), 'delete_email_log_item_' . $item ['ID'] );
96
+ $viewUrl = admin_url( sprintf( $iframeUri, 'view', $item ['ID'] ) );
97
+ $transcriptUrl = admin_url( sprintf( $iframeUri, 'transcript', $item ['ID'] ) );
98
+ $resendUrl = admin_url( sprintf( $iframeUri, 'resend', $item ['ID'] ) );
99
+
100
+ $meta_values = PostmanLogFields::get_instance()->get( $item ['ID'] );
101
+
102
+ $actions = array(
103
+ 'delete' => sprintf( '<a href="%s">%s</a>', $deleteUrl, _x( 'Delete', 'Delete an item from the email log', 'post-smtp' ) ),
104
+ 'view' => sprintf( '<a href="%s" class="thickbox">%s</a>', $viewUrl, _x( 'View', 'View an item from the email log', 'post-smtp' ) ),
105
+ );
106
+
107
+ if ( ! empty( $meta_values ['session_transcript'] [0] ) ) {
108
+ $actions ['transcript'] = sprintf( '<a href="%1$s" class="thickbox">%2$s</a>', $transcriptUrl, __( 'Session Transcript', 'post-smtp' ) );
109
+ } else {
110
+ $actions ['transcript'] = sprintf( '%2$s', $transcriptUrl, __( 'Session Transcript', 'post-smtp' ) );
111
+ }
112
+ if ( ! (empty( $meta_values ['original_to'] [0] ) && empty( $meta_values ['originalHeaders'] [0] )) ) {
113
+ // $actions ['resend'] = sprintf ( '<a href="%s">%s</a>', $resendUrl, __ ( 'Resend', 'post-smtp' ) );
114
+ $emails = $meta_values ['original_to'] [0];
115
+ $to = !is_array( $emails ) ? explode( ',', $emails ) : $emails;
116
+ $to = array_map( 'sanitize_email', $to );
117
+ $to = implode( ',', $to );
118
+
119
+ $actions ['resend'] = sprintf( '<span id="%3$s"><a class="postman-open-resend" href="#">%2$s</a></span><div style="display:none;"><input type="hidden" name="security" value="%6$s"><input type="text" name="mail_to" class="regular-text ltr" data-id="%1$s" value="%4$s"><button class="postman-resend button button-primary">%2$s</button><i style="color: black;">%5$s</i></div>', $item ['ID'], __( 'Resend', 'post-smtp' ), 'resend-' . $item ['ID'], esc_attr( $to ), __( 'comma-separated for multiple emails', 'post-smtp' ), wp_create_nonce( 'resend' ) );
120
+ } else {
121
+ $actions ['resend'] = sprintf( '%2$s', $resendUrl, __( 'Resend', 'post-smtp' ) );
122
+ }
123
+
124
+ // Return the title contents
125
+ return sprintf( '%1$s %3$s',
126
+ /*$1%s*/ $item ['title'],
127
+ /*$2%s*/ $item ['ID'],
128
+ /*$3%s*/ $this->row_actions( $actions ) );
129
+ }
130
+
131
+ /**
132
+ * ************************************************************************
133
+ * REQUIRED if displaying checkboxes or using bulk actions! The 'cb' column
134
+ * is given special treatment when columns are processed.
135
+ * It ALWAYS needs to
136
+ * have it's own method.
137
+ *
138
+ * @see WP_List_Table::::single_row_columns()
139
+ * @param array $item
140
+ * A singular item (one full row's worth of data)
141
+ * @return string Text to be placed inside the column <td> (movie title only)
142
+ * ************************************************************************
143
+ */
144
+ function column_cb( $item ) {
145
+ return sprintf( '<input type="checkbox" name="%1$s[]" value="%2$s" />',
146
+ /*$1%s*/ $this->_args ['singular'], // Let's simply repurpose the table's singular label ("movie")
147
+ /* $2%s */
148
+ $item ['ID'] ); // The value of the checkbox should be the record's id
149
+ }
150
+
151
+ /**
152
+ * ************************************************************************
153
+ * REQUIRED! This method dictates the table's columns and titles.
154
+ * This should
155
+ * return an array where the key is the column slug (and class) and the value
156
+ * is the column's title text. If you need a checkbox for bulk actions, refer
157
+ * to the $columns array below.
158
+ *
159
+ * The 'cb' column is treated differently than the rest. If including a checkbox
160
+ * column in your table you must create a column_cb() method. If you don't need
161
+ * bulk actions or checkboxes, simply leave the 'cb' entry out of your array.
162
+ *
163
+ * @see WP_List_Table::::single_row_columns()
164
+ * @return array An associative array containing column information: 'slugs'=>'Visible Titles'
165
+ * ************************************************************************
166
+ */
167
+ function get_columns() {
168
+ $columns = array(
169
+ 'cb' => '<input type="checkbox" />', // Render a checkbox instead of text
170
+ 'title' => _x( 'Subject', 'What is the subject of this message?', 'post-smtp' ),
171
+ 'sent_to' => __( 'Sent To', 'post-smtp' ),
172
+ 'status' => __( 'Status', 'post-smtp' ),
173
+ 'solution' => __( 'Solution', 'post-smtp' ),
174
+ 'date' => _x( 'Delivery Time', 'When was this email sent?', 'post-smtp' ),
175
+ );
176
+ return $columns;
177
+ }
178
+
179
+ /**
180
+ * ************************************************************************
181
+ * Optional.
182
+ * If you want one or more columns to be sortable (ASC/DESC toggle),
183
+ * you will need to register it here. This should return an array where the
184
+ * key is the column that needs to be sortable, and the value is db column to
185
+ * sort by. Often, the key and value will be the same, but this is not always
186
+ * the case (as the value is a column name from the database, not the list table).
187
+ *
188
+ * This method merely defines which columns should be sortable and makes them
189
+ * clickable - it does not handle the actual sorting. You still need to detect
190
+ * the ORDERBY and ORDER querystring variables within prepare_items() and sort
191
+ * your data accordingly (usually by modifying your query).
192
+ *
193
+ * @return array An associative array containing all the columns that should be sortable: 'slugs'=>array('data_values',bool)
194
+ * ************************************************************************
195
+ */
196
+ function get_sortable_columns() {
197
+ return array();
198
+ $sortable_columns = array(
199
+ 'title' => array(
200
+ 'title',
201
+ false,
202
+ ), // true means it's already sorted
203
+ 'status' => array(
204
+ 'status',
205
+ false,
206
+ ),
207
+ 'date' => array(
208
+ 'date',
209
+ false,
210
+ ),
211
+ );
212
+ return $sortable_columns;
213
+ }
214
+
215
+ /**
216
+ * ************************************************************************
217
+ * Optional.
218
+ * If you need to include bulk actions in your list table, this is
219
+ * the place to define them. Bulk actions are an associative array in the format
220
+ * 'slug'=>'Visible Title'
221
+ *
222
+ * If this method returns an empty value, no bulk action will be rendered. If
223
+ * you specify any bulk actions, the bulk actions box will be rendered with
224
+ * the table automatically on display().
225
+ *
226
+ * Also note that list tables are not automatically wrapped in <form> elements,
227
+ * so you will need to create those manually in order for bulk actions to function.
228
+ *
229
+ * @return array An associative array containing all the bulk actions: 'slugs'=>'Visible Titles'
230
+ * ************************************************************************
231
+ */
232
+ function get_bulk_actions() {
233
+ $actions = array(
234
+ 'bulk_delete' => _x( 'Delete', 'Delete an item from the email log', 'post-smtp' ),
235
+ );
236
+ return $actions;
237
+ }
238
+
239
+ /**
240
+ * ************************************************************************
241
+ * Optional.
242
+ * You can handle your bulk actions anywhere or anyhow you prefer.
243
+ * For this example package, we will handle it in the class to keep things
244
+ * clean and organized.
245
+ *
246
+ * @see $this->prepare_items() ************************************************************************
247
+ */
248
+ function process_bulk_action() {
249
+ }
250
+
251
+ /**
252
+ * ************************************************************************
253
+ * REQUIRED! This is where you prepare your data for display.
254
+ * This method will
255
+ * usually be used to query the database, sort and filter the data, and generally
256
+ * get it ready to be displayed. At a minimum, we should set $this->items and
257
+ * $this->set_pagination_args(), although the following properties and methods
258
+ * are frequently interacted with here...
259
+ *
260
+ * @global WPDB $wpdb
261
+ * @uses $this->_column_headers
262
+ * @uses $this->items
263
+ * @uses $this->get_columns()
264
+ * @uses $this->get_sortable_columns()
265
+ * @uses $this->get_pagenum()
266
+ * @uses $this->set_pagination_args()
267
+ * ************************************************************************
268
+ */
269
+ function prepare_items() {
270
+
271
+ if ( ! current_user_can( Postman::MANAGE_POSTMAN_CAPABILITY_LOGS ) ) {
272
+ wp_die( sprintf( 'You need to add to this user the %s capability. You can try disable and enable the plugin or you can do it with a plugin like `user role editor`.', Postman::MANAGE_POSTMAN_CAPABILITY_LOGS ) );
273
+ }
274
+
275
+ /**
276
+ * First, lets decide how many records per page to show
277
+ */
278
+ $per_page = isset( $_GET['postman_page_records'] ) ? absint( $_GET['postman_page_records'] ) : 10;
279
+
280
+ /**
281
+ * REQUIRED.
282
+ * Now we need to define our column headers. This includes a complete
283
+ * array of columns to be displayed (slugs & titles), a list of columns
284
+ * to keep hidden, and a list of columns that are sortable. Each of these
285
+ * can be defined in another method (as we've done here) before being
286
+ * used to build the value for our _column_headers property.
287
+ */
288
+ $columns = $this->get_columns();
289
+ $hidden = array();
290
+ $sortable = $this->get_sortable_columns();
291
+
292
+ /**
293
+ * REQUIRED.
294
+ * Finally, we build an array to be used by the class for column
295
+ * headers. The $this->_column_headers property takes an array which contains
296
+ * 3 other arrays. One for all columns, one for hidden columns, and one
297
+ * for sortable columns.
298
+ */
299
+ $this->_column_headers = array(
300
+ $columns,
301
+ $hidden,
302
+ $sortable,
303
+ );
304
+
305
+ /**
306
+ * Optional.
307
+ * You can handle your bulk actions however you see fit. In this
308
+ * case, we'll handle them within our package just to keep things clean.
309
+ */
310
+ $this->process_bulk_action();
311
+
312
+ /**
313
+ * Instead of querying a database, we're going to fetch the example data
314
+ * property we created for use in this plugin.
315
+ * This makes this example
316
+ * package slightly different than one you might build on your own. In
317
+ * this example, we'll be using array manipulation to sort and paginate
318
+ * our data. In a real-world implementation, you will probably want to
319
+ * use sort and pagination data to build a custom query instead, as you'll
320
+ * be able to use your precisely-queried data immediately.
321
+ */
322
+ $data = array();
323
+
324
+ $args = array(
325
+ 'posts_per_page' => -1,
326
+ 'orderby' => 'date',
327
+ 'order' => 'DESC',
328
+ 'post_type' => PostmanEmailLogPostType::POSTMAN_CUSTOM_POST_TYPE_SLUG,
329
+ 'post_status' => 'private',
330
+ 'suppress_filters' => true,
331
+ );
332
+
333
+ if ( isset( $_GET['from_date'] ) && ! empty( $_GET['from_date'] ) ) {
334
+ $from_date = sanitize_text_field( $_GET['from_date'] );
335
+
336
+ $args['date_query']['after'] = $from_date;
337
+ $args['date_query']['column'] = 'post_date';
338
+ $args['date_query']['inclusive'] = false;
339
+ }
340
+
341
+ if ( isset( $_GET['to_date'] ) && ! empty( $_GET['to_date'] ) ) {
342
+ $to_date = sanitize_text_field( $_GET['to_date'] );
343
+
344
+ $args['date_query']['before'] = $to_date;
345
+ $args['date_query']['column'] = 'post_date';
346
+ $args['date_query']['inclusive'] = true;
347
+ }
348
+
349
+ if ( ! empty( $_GET['search'] ) ) {
350
+
351
+ if ( isset( $args['date_query'] ) ) {
352
+ unset( $args['date_query'] ); }
353
+
354
+ $args['s'] = sanitize_text_field( $_GET['search'] );
355
+ }
356
+
357
+ if ( isset( $_GET['postman_trash_all'] ) ) {
358
+ $args['posts_per_page'] = -1;
359
+ }
360
+ $posts = new WP_query( $args );
361
+
362
+ $date_format = get_option( 'date_format' );
363
+ $time_format = get_option( 'time_format' );
364
+
365
+ foreach ( $posts->posts as $post ) {
366
+ $date = $post->post_date;
367
+ $humanTime = human_time_diff( strtotime( $post->post_date_gmt ) );
368
+ // if this PHP system support humanTime, than use it
369
+ if ( ! empty( $humanTime ) ) {
370
+ /* Translators: where %s indicates the relative time from now */
371
+ $date = sprintf( _x( '%s ago', 'A relative time as in "five days ago"', 'post-smtp' ), $humanTime );
372
+ }
373
+ $meta_values = PostmanLogFields::get_instance()->get( $post->ID );
374
+ $sent_to = array_map( 'esc_html', explode( ',' , $meta_values ['to_header'] [0] ) );
375
+ $solution_meta = $meta_values ['solution'] [0];
376
+
377
+ if ( empty( $solution_meta ) && empty( $post->post_excerpt ) ) {
378
+ $solution = 'No need - Mail sent';
379
+ } else {
380
+ $solution = $solution_meta;
381
+ }
382
+
383
+ $flattenedPost = array(
384
+ // the post title must be escaped as they are displayed in the HTML output
385
+ 'sent_to' => implode( ', ', $sent_to ),
386
+ 'title' => esc_html( $post->post_title ),
387
+ 'solution' => $solution,
388
+ // the post status must be escaped as they are displayed in the HTML output
389
+ 'status' => ($post->post_excerpt != null ? esc_html( $post->post_excerpt ) : __( 'Sent', 'post-smtp' )),
390
+ 'date' => date( "$date_format $time_format", strtotime( $post->post_date ) ),
391
+ 'ID' => $post->ID,
392
+ );
393
+ array_push( $data, $flattenedPost );
394
+ }
395
+
396
+ /**
397
+ * *********************************************************************
398
+ * ---------------------------------------------------------------------
399
+ * vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
400
+ *
401
+ * In a real-world situation, this is where you would place your query.
402
+ *
403
+ * For information on making queries in WordPress, see this Codex entry:
404
+ * http://codex.wordpress.org/Class_Reference/wpdb
405
+ *
406
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
407
+ * ---------------------------------------------------------------------
408
+ * ********************************************************************
409
+ */
410
+
411
+ /**
412
+ * REQUIRED for pagination.
413
+ * Let's figure out what page the user is currently
414
+ * looking at. We'll need this later, so you should always include it in
415
+ * your own package classes.
416
+ */
417
+ $current_page = $this->get_pagenum();
418
+
419
+ /**
420
+ * REQUIRED for pagination.
421
+ * Let's check how many items are in our data array.
422
+ * In real-world use, this would be the total number of items in your database,
423
+ * without filtering. We'll need this later, so you should always include it
424
+ * in your own package classes.
425
+ */
426
+ $total_items = count( $data );
427
+
428
+ /**
429
+ * The WP_List_Table class does not handle pagination for us, so we need
430
+ * to ensure that the data is trimmed to only the current page.
431
+ * We can use
432
+ * array_slice() to
433
+ */
434
+ $data = array_slice( $data, (($current_page - 1) * $per_page), $per_page );
435
+
436
+ /**
437
+ * REQUIRED.
438
+ * Now we can add our *sorted* data to the items property, where
439
+ * it can be used by the rest of the class.
440
+ */
441
+ $this->items = $data;
442
+
443
+ /**
444
+ * REQUIRED.
445
+ * We also have to register our pagination options & calculations.
446
+ */
447
+ $this->set_pagination_args( array(
448
+ 'total_items' => $total_items, // WE have to calculate the total number of items
449
+ 'per_page' => $per_page, // WE have to determine how many items to show on a page
450
+ 'total_pages' => ceil( $total_items / $per_page ),
451
+ ) ); // WE have to calculate the total number of pages
452
+ }
453
+ }
454
+
Postman/Postman-Mail/PostmanContactForm7.php CHANGED
@@ -1,42 +1,42 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
- class Postsmtp_ContactForm7 {
6
-
7
- private $result_error;
8
-
9
- public function __construct() {
10
- add_action( 'wpcf7_mail_failed', array( $this, 'save_error' ) );
11
- add_filter( 'wpcf7_ajax_json_echo', array( $this, 'change_rest_response' ), 10, 2 );
12
- }
13
-
14
- public function save_error($contact_form) {
15
- $this->result_error = apply_filters( 'postman_wp_mail_result', null );
16
- }
17
-
18
- public function change_rest_response( $response ) {
19
- if ( array_key_exists('status', $response) && $response['status'] == 'mail_failed' ) {
20
- $message = $this->result_error ['exception']->getMessage();
21
-
22
- if ( ! $message || $message == '' ) {
23
- return $response;
24
- }
25
-
26
- $currentTransport = PostmanOptions::getInstance()->getTransportType();
27
- $result = json_decode($message);
28
- $is_json = (json_last_error() == JSON_ERROR_NONE);
29
-
30
- switch ($currentTransport) {
31
- case 'gmail_api':
32
- $response['message'] = $is_json ? $result->error->message : $message;
33
- break;
34
- default:
35
- $response['message'] = $is_json ? json_encode(json_decode($message), JSON_PRETTY_PRINT) : $message;
36
- }
37
- }
38
-
39
- return $response;
40
- }
41
-
42
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+ class Postsmtp_ContactForm7 {
6
+
7
+ private $result_error;
8
+
9
+ public function __construct() {
10
+ add_action( 'wpcf7_mail_failed', array( $this, 'save_error' ) );
11
+ add_filter( 'wpcf7_ajax_json_echo', array( $this, 'change_rest_response' ), 10, 2 );
12
+ }
13
+
14
+ public function save_error($contact_form) {
15
+ $this->result_error = apply_filters( 'postman_wp_mail_result', null );
16
+ }
17
+
18
+ public function change_rest_response( $response ) {
19
+ if ( array_key_exists('status', $response) && $response['status'] == 'mail_failed' ) {
20
+ $message = $this->result_error ['exception']->getMessage();
21
+
22
+ if ( ! $message || $message == '' ) {
23
+ return $response;
24
+ }
25
+
26
+ $currentTransport = PostmanOptions::getInstance()->getTransportType();
27
+ $result = json_decode($message);
28
+ $is_json = (json_last_error() == JSON_ERROR_NONE);
29
+
30
+ switch ($currentTransport) {
31
+ case 'gmail_api':
32
+ $response['message'] = $is_json ? $result->error->message : $message;
33
+ break;
34
+ default:
35
+ $response['message'] = $is_json ? json_encode(json_decode($message), JSON_PRETTY_PRINT) : $message;
36
+ }
37
+ }
38
+
39
+ return $response;
40
+ }
41
+
42
+ }
Postman/Postman-Mail/PostmanDefaultModuleTransport.php CHANGED
@@ -1,179 +1,179 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- require_once 'PostmanModuleTransport.php';
7
- if (! class_exists ( 'PostmanSmtpModuleTransport' )) {
8
- class PostmanDefaultModuleTransport extends PostmanAbstractZendModuleTransport implements PostmanZendModuleTransport {
9
- const SLUG = 'default';
10
- private $fromName;
11
- private $fromEmail;
12
-
13
- /**
14
- *
15
- * @param mixed $rootPluginFilenameAndPath
16
- */
17
- public function __construct($rootPluginFilenameAndPath) {
18
- parent::__construct ( $rootPluginFilenameAndPath );
19
- $this->init ();
20
- }
21
-
22
- /**
23
- * Copied from WordPress core
24
- * Set the from name and email
25
- */
26
- public function init() {
27
- parent::init();
28
- // From email and name
29
- // If we don't have a name from the input headers
30
- $this->fromName = apply_filters( 'wp_mail_from_name', 'WordPress' );
31
-
32
- /*
33
- * If we don't have an email from the input headers default to wordpress@$sitename
34
- * Some hosts will block outgoing mail from this address if it doesn't exist but
35
- * there's no easy alternative. Defaulting to admin_email might appear to be another
36
- * option but some hosts may refuse to relay mail from an unknown domain. See
37
- * https://core.trac.wordpress.org/ticket/5007.
38
- */
39
-
40
- // Get the site domain and get rid of www.
41
- $site_url = get_bloginfo( 'url' );
42
- $sitename = strtolower ( PostmanUtils::getHost( $site_url ) );
43
-
44
- $this->fromEmail = apply_filters( 'wp_mail_from', 'wordpress@' . $sitename );
45
- }
46
- public function isConfiguredAndReady() {
47
- return false;
48
- }
49
- public function isReadyToSendMail() {
50
- return true;
51
- }
52
- public function getFromEmailAddress() {
53
- return $this->fromEmail;
54
- }
55
- public function getFromName() {
56
- return $this->fromName;
57
- }
58
- public function getEnvelopeFromEmailAddress() {
59
- return $this->getFromEmailAddress ();
60
- }
61
- public function isEmailValidationSupported() {
62
- return false;
63
- }
64
-
65
- /**
66
- * (non-PHPdoc)
67
- *
68
- * @see PostmanAbstractZendModuleTransport::validateTransportConfiguration()
69
- */
70
- protected function validateTransportConfiguration() {
71
- return array ();
72
- // no-op, always valid
73
- }
74
-
75
- /**
76
- * (non-PHPdoc)
77
- *
78
- * @see PostmanModuleTransport::createMailEngine()
79
- */
80
- public function createMailEngine() {
81
- require_once 'PostmanZendMailEngine.php';
82
- return new PostmanZendMailEngine ( $this );
83
- }
84
-
85
- /**
86
- * (non-PHPdoc)
87
- *
88
- * @see PostmanZendModuleTransport::createZendMailTransport()
89
- */
90
- public function createZendMailTransport($fakeHostname, $fakeConfig) {
91
- $config = array (
92
- 'port' => $this->getPort ()
93
- );
94
- return new Postman_Zend_Mail_Transport_Smtp ( $this->getHostname (), $config );
95
- }
96
-
97
- /**
98
- * Determines whether Mail Engine locking is needed
99
- *
100
- * @see PostmanModuleTransport::requiresLocking()
101
- */
102
- public function isLockingRequired() {
103
- return PostmanOptions::AUTHENTICATION_TYPE_OAUTH2 == $this->getAuthenticationType ();
104
- }
105
- public function getSlug() {
106
- return self::SLUG;
107
- }
108
- public function getName() {
109
- return __ ( 'Default', 'post-smtp' );
110
- }
111
- public function getHostname() {
112
- return 'localhost';
113
- }
114
- public function getPort() {
115
- return 25;
116
- }
117
- public function getSecurityType() {
118
- return PostmanOptions::SECURITY_TYPE_NONE;
119
- }
120
- public function getAuthenticationType() {
121
- return PostmanOptions::AUTHENTICATION_TYPE_NONE;
122
- }
123
- public function getCredentialsId() {
124
- $options = PostmanOptions::getInstance ();
125
- if ($options->isAuthTypeOAuth2 ()) {
126
- return $options->getClientId ();
127
- } else {
128
- return $options->getUsername ();
129
- }
130
- }
131
- public function getCredentialsSecret() {
132
- $options = PostmanOptions::getInstance ();
133
- if ($options->isAuthTypeOAuth2 ()) {
134
- return $options->getClientSecret ();
135
- } else {
136
- return $options->getPassword ();
137
- }
138
- }
139
- public function isServiceProviderGoogle($hostname) {
140
- return PostmanUtils::endsWith ( $hostname, 'gmail.com' );
141
- }
142
- public function isServiceProviderMicrosoft($hostname) {
143
- return PostmanUtils::endsWith ( $hostname, 'live.com' );
144
- }
145
- public function isServiceProviderYahoo($hostname) {
146
- return strpos ( $hostname, 'yahoo' );
147
- }
148
- public function isOAuthUsed($authType) {
149
- return false;
150
- }
151
- public final function getConfigurationBid(PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer) {
152
- return null;
153
- }
154
-
155
- /**
156
- * Does not participate in the Wizard process;
157
- *
158
- * (non-PHPdoc)
159
- *
160
- * @see PostmanModuleTransport::getSocketsForSetupWizardToProbe()
161
- */
162
- public function getSocketsForSetupWizardToProbe($hostname, $smtpServerGuess) {
163
- return array ();
164
- }
165
-
166
-
167
- /**
168
- * Returns true, to prevent from errors because it's default Module Transport.
169
- *
170
- * @since 2.1.4
171
- * @version 1.0
172
- */
173
- public function has_granted() {
174
-
175
- return true;
176
-
177
- }
178
- }
179
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ require_once 'PostmanModuleTransport.php';
7
+ if (! class_exists ( 'PostmanSmtpModuleTransport' )) {
8
+ class PostmanDefaultModuleTransport extends PostmanAbstractZendModuleTransport implements PostmanZendModuleTransport {
9
+ const SLUG = 'default';
10
+ private $fromName;
11
+ private $fromEmail;
12
+
13
+ /**
14
+ *
15
+ * @param mixed $rootPluginFilenameAndPath
16
+ */
17
+ public function __construct($rootPluginFilenameAndPath) {
18
+ parent::__construct ( $rootPluginFilenameAndPath );
19
+ $this->init ();
20
+ }
21
+
22
+ /**
23
+ * Copied from WordPress core
24
+ * Set the from name and email
25
+ */
26
+ public function init() {
27
+ parent::init();
28
+ // From email and name
29
+ // If we don't have a name from the input headers
30
+ $this->fromName = apply_filters( 'wp_mail_from_name', 'WordPress' );
31
+
32
+ /*
33
+ * If we don't have an email from the input headers default to wordpress@$sitename
34
+ * Some hosts will block outgoing mail from this address if it doesn't exist but
35
+ * there's no easy alternative. Defaulting to admin_email might appear to be another
36
+ * option but some hosts may refuse to relay mail from an unknown domain. See
37
+ * https://core.trac.wordpress.org/ticket/5007.
38
+ */
39
+
40
+ // Get the site domain and get rid of www.
41
+ $site_url = get_bloginfo( 'url' );
42
+ $sitename = strtolower ( PostmanUtils::getHost( $site_url ) );
43
+
44
+ $this->fromEmail = apply_filters( 'wp_mail_from', 'wordpress@' . $sitename );
45
+ }
46
+ public function isConfiguredAndReady() {
47
+ return false;
48
+ }
49
+ public function isReadyToSendMail() {
50
+ return true;
51
+ }
52
+ public function getFromEmailAddress() {
53
+ return $this->fromEmail;
54
+ }
55
+ public function getFromName() {
56
+ return $this->fromName;
57
+ }
58
+ public function getEnvelopeFromEmailAddress() {
59
+ return $this->getFromEmailAddress ();
60
+ }
61
+ public function isEmailValidationSupported() {
62
+ return false;
63
+ }
64
+
65
+ /**
66
+ * (non-PHPdoc)
67
+ *
68
+ * @see PostmanAbstractZendModuleTransport::validateTransportConfiguration()
69
+ */
70
+ protected function validateTransportConfiguration() {
71
+ return array ();
72
+ // no-op, always valid
73
+ }
74
+
75
+ /**
76
+ * (non-PHPdoc)
77
+ *
78
+ * @see PostmanModuleTransport::createMailEngine()
79
+ */
80
+ public function createMailEngine() {
81
+ require_once 'PostmanZendMailEngine.php';
82
+ return new PostmanZendMailEngine ( $this );
83
+ }
84
+
85
+ /**
86
+ * (non-PHPdoc)
87
+ *
88
+ * @see PostmanZendModuleTransport::createZendMailTransport()
89
+ */
90
+ public function createZendMailTransport($fakeHostname, $fakeConfig) {
91
+ $config = array (
92
+ 'port' => $this->getPort ()
93
+ );
94
+ return new Postman_Zend_Mail_Transport_Smtp ( $this->getHostname (), $config );
95
+ }
96
+
97
+ /**
98
+ * Determines whether Mail Engine locking is needed
99
+ *
100
+ * @see PostmanModuleTransport::requiresLocking()
101
+ */
102
+ public function isLockingRequired() {
103
+ return PostmanOptions::AUTHENTICATION_TYPE_OAUTH2 == $this->getAuthenticationType ();
104
+ }
105
+ public function getSlug() {
106
+ return self::SLUG;
107
+ }
108
+ public function getName() {
109
+ return __ ( 'Default', 'post-smtp' );
110
+ }
111
+ public function getHostname() {
112
+ return 'localhost';
113
+ }
114
+ public function getPort() {
115
+ return 25;
116
+ }
117
+ public function getSecurityType() {
118
+ return PostmanOptions::SECURITY_TYPE_NONE;
119
+ }
120
+ public function getAuthenticationType() {
121
+ return PostmanOptions::AUTHENTICATION_TYPE_NONE;
122
+ }
123
+ public function getCredentialsId() {
124
+ $options = PostmanOptions::getInstance ();
125
+ if ($options->isAuthTypeOAuth2 ()) {
126
+ return $options->getClientId ();
127
+ } else {
128
+ return $options->getUsername ();
129
+ }
130
+ }
131
+ public function getCredentialsSecret() {
132
+ $options = PostmanOptions::getInstance ();
133
+ if ($options->isAuthTypeOAuth2 ()) {
134
+ return $options->getClientSecret ();
135
+ } else {
136
+ return $options->getPassword ();
137
+ }
138
+ }
139
+ public function isServiceProviderGoogle($hostname) {
140
+ return PostmanUtils::endsWith ( $hostname, 'gmail.com' );
141
+ }
142
+ public function isServiceProviderMicrosoft($hostname) {
143
+ return PostmanUtils::endsWith ( $hostname, 'live.com' );
144
+ }
145
+ public function isServiceProviderYahoo($hostname) {
146
+ return strpos ( $hostname, 'yahoo' );
147
+ }
148
+ public function isOAuthUsed($authType) {
149
+ return false;
150
+ }
151
+ public final function getConfigurationBid(PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer) {
152
+ return null;
153
+ }
154
+
155
+ /**
156
+ * Does not participate in the Wizard process;
157
+ *
158
+ * (non-PHPdoc)
159
+ *
160
+ * @see PostmanModuleTransport::getSocketsForSetupWizardToProbe()
161
+ */
162
+ public function getSocketsForSetupWizardToProbe($hostname, $smtpServerGuess) {
163
+ return array ();
164
+ }
165
+
166
+
167
+ /**
168
+ * Returns true, to prevent from errors because it's default Module Transport.
169
+ *
170
+ * @since 2.1.4
171
+ * @version 1.0
172
+ */
173
+ public function has_granted() {
174
+
175
+ return true;
176
+
177
+ }
178
+ }
179
+ }
Postman/Postman-Mail/PostmanEmailAddress.php CHANGED
@@ -1,95 +1,95 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- if (! class_exists ( 'PostmanEmailAddress' )) {
7
- class PostmanEmailAddress {
8
- private $name;
9
- private $email;
10
- public function __construct($email, $name = null) {
11
- // Break $recipient into name and address parts if in the format "Foo <bar@baz.com>"
12
- if (preg_match ( '/(.*)<(.+)>/', $email, $matches )) {
13
- if (count ( $matches ) == 3) {
14
- $name = $matches [1];
15
- $email = $matches [2];
16
- }
17
- }
18
- $this->setEmail ( trim ( $email ) );
19
- $this->setName ( trim ( $name ) );
20
- }
21
- public static function copy(PostmanEmailAddress $orig) {
22
- return new PostmanEmailAddress ( $orig->getEmail (), $orig->getName () );
23
- }
24
- public function getName() {
25
- return $this->name;
26
- }
27
- public function getEmail() {
28
- return $this->email;
29
- }
30
- public function format() {
31
- $name = $this->getName ();
32
- if (! empty ( $name )) {
33
- return sprintf ( '%s <%s>', $this->getName (), $this->getEmail () );
34
- } else {
35
- return sprintf ( '%s', $this->getEmail () );
36
- }
37
- }
38
- public function setName($name) {
39
- $this->name = $name;
40
- }
41
- public function setEmail($email) {
42
- $this->email = $email;
43
- }
44
-
45
- /**
46
- * Validate the email address
47
- *
48
- * @throws Exception
49
- */
50
- public function validate($desc = '') {
51
- if (! PostmanUtils::validateEmail ( $this->email )) {
52
- if (empty ( $desc )) {
53
- /* Translators: Where %s is the email address */
54
- $message = sprintf ( 'Invalid e-mail address "%s"', $this->email );
55
- } else {
56
- /* Translators: Where (1) is the header name (eg. To) and (2) is the email address */
57
- $message = sprintf ( 'Invalid "%1$s" e-mail address "%2$s"', $desc, $this->email );
58
- }
59
- $logger = new PostmanLogger ( get_class ( $this ) );
60
- $logger->warn ( $message );
61
- throw new Exception ( $message );
62
- }
63
- }
64
-
65
- /**
66
- * Accept a String of addresses or an array and return an array
67
- *
68
- * @param mixed $recipientList
69
- * @param mixed $recipients
70
- */
71
- public static function convertToArray($emails) {
72
- assert ( ! empty ( $emails ) );
73
- if (! is_array ( $emails )) {
74
- // http://tiku.io/questions/955963/splitting-comma-separated-email-addresses-in-a-string-with-commas-in-quotes-in-p
75
- $t = str_getcsv ( $emails );
76
- $emails = array ();
77
- foreach ( $t as $k => $v ) {
78
- if (strpos ( $v, ',' ) !== false) {
79
- $t [$k] = '"' . str_replace ( ' <', '" <', $v );
80
- }
81
- $tokenizedEmail = trim ( $t [$k] );
82
- array_push ( $emails, $tokenizedEmail );
83
- }
84
- }
85
- return $emails;
86
- }
87
- public function log(PostmanLogger $log, $desc) {
88
- $message = $desc . ' email=' . $this->getEmail ();
89
- if (! empty ( $this->name )) {
90
- $message .= ' name=' . $this->getName ();
91
- }
92
- $log->debug ( $message );
93
- }
94
- }
95
  }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ if (! class_exists ( 'PostmanEmailAddress' )) {
7
+ class PostmanEmailAddress {
8
+ private $name;
9
+ private $email;
10
+ public function __construct($email, $name = null) {
11
+ // Break $recipient into name and address parts if in the format "Foo <bar@baz.com>"
12
+ if (preg_match ( '/(.*)<(.+)>/', $email, $matches )) {
13
+ if (count ( $matches ) == 3) {
14
+ $name = $matches [1];
15
+ $email = $matches [2];
16
+ }
17
+ }
18
+ $this->setEmail ( trim ( $email ) );
19
+ $this->setName ( trim ( $name ) );
20
+ }
21
+ public static function copy(PostmanEmailAddress $orig) {
22
+ return new PostmanEmailAddress ( $orig->getEmail (), $orig->getName () );
23
+ }
24
+ public function getName() {
25
+ return $this->name;
26
+ }
27
+ public function getEmail() {
28
+ return $this->email;
29
+ }
30
+ public function format() {
31
+ $name = $this->getName ();
32
+ if (! empty ( $name )) {
33
+ return sprintf ( '%s <%s>', $this->getName (), $this->getEmail () );
34
+ } else {
35
+ return sprintf ( '%s', $this->getEmail () );
36
+ }
37
+ }
38
+ public function setName($name) {
39
+ $this->name = $name;
40
+ }
41
+ public function setEmail($email) {
42
+ $this->email = $email;
43
+ }
44
+
45
+ /**
46
+ * Validate the email address
47
+ *
48
+ * @throws Exception
49
+ */
50
+ public function validate($desc = '') {
51
+ if (! PostmanUtils::validateEmail ( $this->email )) {
52
+ if (empty ( $desc )) {
53
+ /* Translators: Where %s is the email address */
54
+ $message = sprintf ( 'Invalid e-mail address "%s"', $this->email );
55
+ } else {
56
+ /* Translators: Where (1) is the header name (eg. To) and (2) is the email address */
57
+ $message = sprintf ( 'Invalid "%1$s" e-mail address "%2$s"', $desc, $this->email );
58
+ }
59
+ $logger = new PostmanLogger ( get_class ( $this ) );
60
+ $logger->warn ( $message );
61
+ throw new Exception ( $message );
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Accept a String of addresses or an array and return an array
67
+ *
68
+ * @param mixed $recipientList
69
+ * @param mixed $recipients
70
+ */
71
+ public static function convertToArray($emails) {
72
+ assert ( ! empty ( $emails ) );
73
+ if (! is_array ( $emails )) {
74
+ // http://tiku.io/questions/955963/splitting-comma-separated-email-addresses-in-a-string-with-commas-in-quotes-in-p
75
+ $t = str_getcsv ( $emails );
76
+ $emails = array ();
77
+ foreach ( $t as $k => $v ) {
78
+ if (strpos ( $v, ',' ) !== false) {
79
+ $t [$k] = '"' . str_replace ( ' <', '" <', $v );
80
+ }
81
+ $tokenizedEmail = trim ( $t [$k] );
82
+ array_push ( $emails, $tokenizedEmail );
83
+ }
84
+ }
85
+ return $emails;
86
+ }
87
+ public function log(PostmanLogger $log, $desc) {
88
+ $message = $desc . ' email=' . $this->getEmail ();
89
+ if (! empty ( $this->name )) {
90
+ $message .= ' name=' . $this->getName ();
91
+ }
92
+ $log->debug ( $message );
93
+ }
94
+ }
95
  }
Postman/Postman-Mail/PostmanGmailApiModuleTransport.php CHANGED
@@ -1,308 +1,308 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- require_once 'PostmanModuleTransport.php';
7
-
8
- /**
9
- * This class integrates Postman with the Gmail API
10
- * http://ctrlq.org/code/19860-gmail-api-send-emails
11
- *
12
- * @author jasonhendriks
13
- *
14
- */
15
- class PostmanGmailApiModuleTransport extends PostmanAbstractZendModuleTransport implements PostmanZendModuleTransport {
16
- const SLUG = 'gmail_api';
17
- const PORT = 443;
18
- const HOST = 'www.googleapis.com';
19
- const ENCRYPTION_TYPE = 'ssl';
20
- const PRIORITY = 27000;
21
- public function __construct($rootPluginFilenameAndPath) {
22
- parent::__construct ( $rootPluginFilenameAndPath );
23
-
24
- // add a hook on the plugins_loaded event
25
- add_action ( 'admin_init', array (
26
- $this,
27
- 'on_admin_init'
28
- ) );
29
- }
30
- public function getProtocol() {
31
- return 'https';
32
- }
33
-
34
- /**
35
- * (non-PHPdoc)
36
- *
37
- * @see PostmanAbstractModuleTransport::isServiceProviderGoogle()
38
- */
39
- public function isServiceProviderGoogle($hostname) {
40
- return true;
41
- }
42
-
43
- /**
44
- * (non-PHPdoc)
45
- *
46
- * @see PostmanModuleTransport::createMailEngine()
47
- */
48
- public function createMailEngine() {
49
- require_once 'PostmanZendMailEngine.php';
50
- return new PostmanZendMailEngine ( $this );
51
- }
52
-
53
- /**
54
- * (non-PHPdoc)
55
- *
56
- * @see PostmanZendModuleTransport::createZendMailTransport()
57
- */
58
- public function createZendMailTransport($fakeHostname, $fakeConfig) {
59
- if (PostmanOptions::AUTHENTICATION_TYPE_OAUTH2 == $this->getAuthenticationType ()) {
60
- $config = PostmanOAuth2ConfigurationFactory::createConfig ( $this );
61
- } else {
62
- $config = PostmanBasicAuthConfigurationFactory::createConfig ( $this );
63
- }
64
-
65
- // Google's autoloader will try and load this so we list it first
66
- require_once 'PostmanGmailApiModuleZendMailTransport.php';
67
-
68
- // Gmail Client includes
69
- require_once 'google-api-client/vendor/autoload.php';
70
-
71
- // build the Gmail Client
72
- $authToken = PostmanOAuthToken::getInstance ();
73
- $client = new Google_Client ();
74
- $client->setClientId ( $this->options->getClientId () );
75
- $client->setClientSecret ( $this->options->getClientSecret () );
76
- $client->setRedirectUri ( '' );
77
- // rebuild the google access token
78
- $token = new stdClass ();
79
- $token->access_token = $authToken->getAccessToken ();
80
- $token->refresh_token = $authToken->getRefreshToken ();
81
- $token->token_type = 'Bearer';
82
- $token->expires_in = 3600;
83
- $token->id_token = null;
84
- $token->created = 0;
85
- $client->setAccessToken ( json_encode ( $token ) );
86
- // We only need permissions to compose and send emails
87
- $client->addScope ( "https://www.googleapis.com/auth/gmail.compose" );
88
- $service = new Google_Service_Gmail ( $client );
89
- $config [PostmanGmailApiModuleZendMailTransport::SERVICE_OPTION] = $service;
90
-
91
- return new PostmanGmailApiModuleZendMailTransport ( self::HOST, $config );
92
- }
93
-
94
- /**
95
- * Determines whether Mail Engine locking is needed
96
- *
97
- * @see PostmanModuleTransport::requiresLocking()
98
- */
99
- public function isLockingRequired() {
100
- return PostmanOptions::AUTHENTICATION_TYPE_OAUTH2 == $this->getAuthenticationType ();
101
- }
102
- public function getSlug() {
103
- return self::SLUG;
104
- }
105
- public function getName() {
106
- return __ ( 'Gmail API', 'post-smtp' );
107
- }
108
- public function isEnvelopeFromValidationSupported() {
109
- return false;
110
- }
111
- public function getHostname() {
112
- return self::HOST;
113
- }
114
- public function getPort() {
115
- return self::PORT;
116
- }
117
- public function getAuthenticationType() {
118
- return $this->options->getAuthenticationType ();
119
- }
120
- public function getSecurityType() {
121
- return null;
122
- }
123
- public function getCredentialsId() {
124
- $this->options = $this->options;
125
- if ($this->options->isAuthTypeOAuth2 ()) {
126
- return $this->options->getClientId ();
127
- } else {
128
- return $this->options->getUsername ();
129
- }
130
- }
131
- public function getCredentialsSecret() {
132
- $this->options = $this->options;
133
- if ($this->options->isAuthTypeOAuth2 ()) {
134
- return $this->options->getClientSecret ();
135
- } else {
136
- return $this->options->getPassword ();
137
- }
138
- }
139
- public function isServiceProviderMicrosoft($hostname) {
140
- return false;
141
- }
142
- public function isServiceProviderYahoo($hostname) {
143
- return false;
144
- }
145
- public function isOAuthUsed($authType) {
146
- return true;
147
- }
148
-
149
- /**
150
- * (non-PHPdoc)
151
- *
152
- * @see PostmanAbstractModuleTransport::getDeliveryDetails()
153
- */
154
- public function getDeliveryDetails() {
155
- /* translators: where (1) is the secure icon and (2) is the transport name */
156
- return sprintf ( __ ( 'Postman will send mail via the <b>%1$s %2$s</b>.', 'post-smtp' ), '🔐', $this->getName () );
157
- }
158
-
159
- /**
160
- * (non-PHPdoc)
161
- *
162
- * @see PostmanAbstractZendModuleTransport::validateTransportConfiguration()
163
- */
164
- protected function validateTransportConfiguration() {
165
- $messages = parent::validateTransportConfiguration ();
166
- if (empty ( $messages )) {
167
- $this->setReadyForOAuthGrant ();
168
- if ($this->isPermissionNeeded ()) {
169
- /* translators: %1$s is the Client ID label, and %2$s is the Client Secret label */
170
- $message = sprintf ( __ ( 'You have configured OAuth 2.0 authentication, but have not received permission to use it.', 'post-smtp' ), $this->getScribe ()->getClientIdLabel (), $this->getScribe ()->getClientSecretLabel () );
171
- $message .= sprintf ( ' <a href="%s">%s</a>.', PostmanUtils::getGrantOAuthPermissionUrl (), $this->getScribe ()->getRequestPermissionLinkText () );
172
- array_push ( $messages, $message );
173
- $this->setNotConfiguredAndReady ();
174
- }
175
- }
176
- return $messages;
177
- }
178
-
179
- /**
180
- * Given a hostname, what ports should we test?
181
- *
182
- * May return an array of several combinations.
183
- */
184
- public function getSocketsForSetupWizardToProbe($hostname, $smtpServerGuess) {
185
- $hosts = array ();
186
- if ($smtpServerGuess == null || PostmanUtils::isGoogle ( $smtpServerGuess )) {
187
- array_push ( $hosts, parent::createSocketDefinition ( $this->getHostname (), $this->getPort () ) );
188
- }
189
- return $hosts;
190
- }
191
-
192
- /**
193
- * Postman Gmail API supports delivering mail with these parameters:
194
- *
195
- * 70 gmail api on port 465 to www.googleapis.com
196
- *
197
- * @param mixed $hostData
198
- */
199
- public function getConfigurationBid(PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer) {
200
- $recommendation = array ();
201
- $recommendation ['priority'] = 0;
202
- $recommendation ['transport'] = self::SLUG;
203
- $recommendation ['enc'] = PostmanOptions::SECURITY_TYPE_NONE;
204
- $recommendation ['auth'] = PostmanOptions::AUTHENTICATION_TYPE_OAUTH2;
205
- $recommendation ['hostname'] = null; // scribe looks this
206
- $recommendation ['label'] = $this->getName ();
207
- $recommendation ['display_auth'] = 'oauth2';
208
- $recommendation['logo_url'] = $this->getLogoURL();
209
-
210
- if ($hostData->hostname == self::HOST && $hostData->port == self::PORT) {
211
- /* translators: where variables are (1) transport name (2) host and (3) port */
212
- $recommendation ['message'] = sprintf ( __ ( ('Postman recommends the %1$s to host %2$s on port %3$d.') ), $this->getName (), self::HOST, self::PORT );
213
- $recommendation ['priority'] = self::PRIORITY;
214
- }
215
-
216
- return $recommendation;
217
- }
218
-
219
- /**
220
- */
221
- public function createOverrideMenu(PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride) {
222
- $overrideItem = parent::createOverrideMenu ( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
223
- // push the authentication options into the $overrideItem structure
224
- $overrideItem ['auth_items'] = array (
225
- array (
226
- 'selected' => true,
227
- 'name' => __ ( 'OAuth 2.0 (requires Client ID and Client Secret)', 'post-smtp' ),
228
- 'value' => 'oauth2'
229
- )
230
- );
231
- return $overrideItem;
232
- }
233
-
234
- /**
235
- * Functions to execute on the admin_init event
236
- *
237
- * "Runs at the beginning of every admin page before the page is rendered."
238
- * ref: http://codex.wordpress.org/Plugin_API/Action_Reference#Actions_Run_During_an_Admin_Page_Request
239
- */
240
- public function on_admin_init() {
241
- // only administrators should be able to trigger this
242
- if (PostmanUtils::isAdmin ()) {
243
- $this->registerStylesAndScripts ();
244
- }
245
- }
246
-
247
- /**
248
- */
249
- public function registerStylesAndScripts() {
250
- // register the stylesheet and javascript external resources
251
- $pluginData = apply_filters ( 'postman_get_plugin_metadata', null );
252
- wp_register_script ( 'postman_gmail_script', plugins_url ( 'Postman/Postman-Mail/postman_gmail.js', $this->rootPluginFilenameAndPath ), array (
253
- PostmanViewController::JQUERY_SCRIPT,
254
- 'jquery_validation',
255
- PostmanViewController::POSTMAN_SCRIPT
256
- ), $pluginData ['version'] );
257
- }
258
-
259
- /**
260
- */
261
- public function enqueueScript() {
262
- wp_enqueue_script ( 'postman_gmail_script' );
263
- }
264
-
265
- /**
266
- * Get Socket's logo
267
- *
268
- * @since 2.1
269
- * @version 1.0
270
- */
271
- public function getLogoURL() {
272
-
273
- return POST_SMTP_ASSETS . "images/logos/gmail.png";
274
-
275
- }
276
-
277
- /**
278
- * Checks is granted or not
279
- *
280
- * @since 2.1.4
281
- * @version 1.0
282
- */
283
- public function has_granted() {
284
-
285
- if( $this->isPermissionNeeded() ) {
286
- return false;
287
- }
288
-
289
- return true;
290
-
291
- }
292
-
293
- /**
294
- * Returns the HTML of not granted
295
- *
296
- * @since 2.1.4
297
- * @version 1.0
298
- */
299
- public function get_not_granted_notice() {
300
-
301
- return array(
302
- 'message' => __( ' You are just a step away to get started', 'post-smtp' ),
303
- 'url_text' => $this->getScribe()->getRequestPermissionLinkText(),
304
- 'url' => PostmanUtils::getGrantOAuthPermissionUrl()
305
- );
306
-
307
- }
308
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ require_once 'PostmanModuleTransport.php';
7
+
8
+ /**
9
+ * This class integrates Postman with the Gmail API
10
+ * http://ctrlq.org/code/19860-gmail-api-send-emails
11
+ *
12
+ * @author jasonhendriks
13
+ *
14
+ */
15
+ class PostmanGmailApiModuleTransport extends PostmanAbstractZendModuleTransport implements PostmanZendModuleTransport {
16
+ const SLUG = 'gmail_api';
17
+ const PORT = 443;
18
+ const HOST = 'www.googleapis.com';
19
+ const ENCRYPTION_TYPE = 'ssl';
20
+ const PRIORITY = 27000;
21
+ public function __construct($rootPluginFilenameAndPath) {
22
+ parent::__construct ( $rootPluginFilenameAndPath );
23
+
24
+ // add a hook on the plugins_loaded event
25
+ add_action ( 'admin_init', array (
26
+ $this,
27
+ 'on_admin_init'
28
+ ) );
29
+ }
30
+ public function getProtocol() {
31
+ return 'https';
32
+ }
33
+
34
+ /**
35
+ * (non-PHPdoc)
36
+ *
37
+ * @see PostmanAbstractModuleTransport::isServiceProviderGoogle()
38
+ */
39
+ public function isServiceProviderGoogle($hostname) {
40
+ return true;
41
+ }
42
+
43
+ /**
44
+ * (non-PHPdoc)
45
+ *
46
+ * @see PostmanModuleTransport::createMailEngine()
47
+ */
48
+ public function createMailEngine() {
49
+ require_once 'PostmanZendMailEngine.php';
50
+ return new PostmanZendMailEngine ( $this );
51
+ }
52
+
53
+ /**
54
+ * (non-PHPdoc)
55
+ *
56
+ * @see PostmanZendModuleTransport::createZendMailTransport()
57
+ */
58
+ public function createZendMailTransport($fakeHostname, $fakeConfig) {
59
+ if (PostmanOptions::AUTHENTICATION_TYPE_OAUTH2 == $this->getAuthenticationType ()) {
60
+ $config = PostmanOAuth2ConfigurationFactory::createConfig ( $this );
61
+ } else {
62
+ $config = PostmanBasicAuthConfigurationFactory::createConfig ( $this );
63
+ }
64
+
65
+ // Google's autoloader will try and load this so we list it first
66
+ require_once 'PostmanGmailApiModuleZendMailTransport.php';
67
+
68
+ // Gmail Client includes
69
+ require_once 'google-api-client/vendor/autoload.php';
70
+
71
+ // build the Gmail Client
72
+ $authToken = PostmanOAuthToken::getInstance ();
73
+ $client = new Google_Client ();
74
+ $client->setClientId ( $this->options->getClientId () );
75
+ $client->setClientSecret ( $this->options->getClientSecret () );
76
+ $client->setRedirectUri ( '' );
77
+ // rebuild the google access token
78
+ $token = new stdClass ();
79
+ $token->access_token = $authToken->getAccessToken ();
80
+ $token->refresh_token = $authToken->getRefreshToken ();
81
+ $token->token_type = 'Bearer';
82
+ $token->expires_in = 3600;
83
+ $token->id_token = null;
84
+ $token->created = 0;
85
+ $client->setAccessToken ( json_encode ( $token ) );
86
+ // We only need permissions to compose and send emails
87
+ $client->addScope ( "https://www.googleapis.com/auth/gmail.compose" );
88
+ $service = new Google_Service_Gmail ( $client );
89
+ $config [PostmanGmailApiModuleZendMailTransport::SERVICE_OPTION] = $service;
90
+
91
+ return new PostmanGmailApiModuleZendMailTransport ( self::HOST, $config );
92
+ }
93
+
94
+ /**
95
+ * Determines whether Mail Engine locking is needed
96
+ *
97
+ * @see PostmanModuleTransport::requiresLocking()
98
+ */
99
+ public function isLockingRequired() {
100
+ return PostmanOptions::AUTHENTICATION_TYPE_OAUTH2 == $this->getAuthenticationType ();
101
+ }
102
+ public function getSlug() {
103
+ return self::SLUG;
104
+ }
105
+ public function getName() {
106
+ return __ ( 'Gmail API', 'post-smtp' );
107
+ }
108
+ public function isEnvelopeFromValidationSupported() {
109
+ return false;
110
+ }
111
+ public function getHostname() {
112
+ return self::HOST;
113
+ }
114
+ public function getPort() {
115
+ return self::PORT;
116
+ }
117
+ public function getAuthenticationType() {
118
+ return $this->options->getAuthenticationType ();
119
+ }
120
+ public function getSecurityType() {
121
+ return null;
122
+ }
123
+ public function getCredentialsId() {
124
+ $this->options = $this->options;
125
+ if ($this->options->isAuthTypeOAuth2 ()) {
126
+ return $this->options->getClientId ();
127
+ } else {
128
+ return $this->options->getUsername ();
129
+ }
130
+ }
131
+ public function getCredentialsSecret() {
132
+ $this->options = $this->options;
133
+ if ($this->options->isAuthTypeOAuth2 ()) {
134
+ return $this->options->getClientSecret ();
135
+ } else {
136
+ return $this->options->getPassword ();
137
+ }
138
+ }
139
+ public function isServiceProviderMicrosoft($hostname) {
140
+ return false;
141
+ }
142
+ public function isServiceProviderYahoo($hostname) {
143
+ return false;
144
+ }
145
+ public function isOAuthUsed($authType) {
146
+ return true;
147
+ }
148
+
149
+ /**
150
+ * (non-PHPdoc)
151
+ *
152
+ * @see PostmanAbstractModuleTransport::getDeliveryDetails()
153
+ */
154
+ public function getDeliveryDetails() {
155
+ /* translators: where (1) is the secure icon and (2) is the transport name */
156
+ return sprintf ( __ ( 'Postman will send mail via the <b>%1$s %2$s</b>.', 'post-smtp' ), '🔐', $this->getName () );
157
+ }
158
+
159
+ /**
160
+ * (non-PHPdoc)
161
+ *
162
+ * @see PostmanAbstractZendModuleTransport::validateTransportConfiguration()
163
+ */
164
+ protected function validateTransportConfiguration() {
165
+ $messages = parent::validateTransportConfiguration ();
166
+ if (empty ( $messages )) {
167
+ $this->setReadyForOAuthGrant ();
168
+ if ($this->isPermissionNeeded ()) {
169
+ /* translators: %1$s is the Client ID label, and %2$s is the Client Secret label */
170
+ $message = sprintf ( __ ( 'You have configured OAuth 2.0 authentication, but have not received permission to use it.', 'post-smtp' ), $this->getScribe ()->getClientIdLabel (), $this->getScribe ()->getClientSecretLabel () );
171
+ $message .= sprintf ( ' <a href="%s">%s</a>.', PostmanUtils::getGrantOAuthPermissionUrl (), $this->getScribe ()->getRequestPermissionLinkText () );
172
+ array_push ( $messages, $message );
173
+ $this->setNotConfiguredAndReady ();
174
+ }
175
+ }
176
+ return $messages;
177
+ }
178
+
179
+ /**
180
+ * Given a hostname, what ports should we test?
181
+ *
182
+ * May return an array of several combinations.
183
+ */
184
+ public function getSocketsForSetupWizardToProbe($hostname, $smtpServerGuess) {
185
+ $hosts = array ();
186
+ if ($smtpServerGuess == null || PostmanUtils::isGoogle ( $smtpServerGuess )) {
187
+ array_push ( $hosts, parent::createSocketDefinition ( $this->getHostname (), $this->getPort () ) );
188
+ }
189
+ return $hosts;
190
+ }
191
+
192
+ /**
193
+ * Postman Gmail API supports delivering mail with these parameters:
194
+ *
195
+ * 70 gmail api on port 465 to www.googleapis.com
196
+ *
197
+ * @param mixed $hostData
198
+ */
199
+ public function getConfigurationBid(PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer) {
200
+ $recommendation = array ();
201
+ $recommendation ['priority'] = 0;
202
+ $recommendation ['transport'] = self::SLUG;
203
+ $recommendation ['enc'] = PostmanOptions::SECURITY_TYPE_NONE;
204
+ $recommendation ['auth'] = PostmanOptions::AUTHENTICATION_TYPE_OAUTH2;
205
+ $recommendation ['hostname'] = null; // scribe looks this
206
+ $recommendation ['label'] = $this->getName ();
207
+ $recommendation ['display_auth'] = 'oauth2';
208
+ $recommendation['logo_url'] = $this->getLogoURL();
209
+
210
+ if ($hostData->hostname == self::HOST && $hostData->port == self::PORT) {
211
+ /* translators: where variables are (1) transport name (2) host and (3) port */
212
+ $recommendation ['message'] = sprintf ( __ ( ('Postman recommends the %1$s to host %2$s on port %3$d.') ), $this->getName (), self::HOST, self::PORT );
213
+ $recommendation ['priority'] = self::PRIORITY;
214
+ }
215
+
216
+ return $recommendation;
217
+ }
218
+
219
+ /**
220
+ */
221
+ public function createOverrideMenu(PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride) {
222
+ $overrideItem = parent::createOverrideMenu ( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
223
+ // push the authentication options into the $overrideItem structure
224
+ $overrideItem ['auth_items'] = array (
225
+ array (
226
+ 'selected' => true,
227
+ 'name' => __ ( 'OAuth 2.0 (requires Client ID and Client Secret)', 'post-smtp' ),
228
+ 'value' => 'oauth2'
229
+ )
230
+ );
231
+ return $overrideItem;
232
+ }
233
+
234
+ /**
235
+ * Functions to execute on the admin_init event
236
+ *
237
+ * "Runs at the beginning of every admin page before the page is rendered."
238
+ * ref: http://codex.wordpress.org/Plugin_API/Action_Reference#Actions_Run_During_an_Admin_Page_Request
239
+ */
240
+ public function on_admin_init() {
241
+ // only administrators should be able to trigger this
242
+ if (PostmanUtils::isAdmin ()) {
243
+ $this->registerStylesAndScripts ();
244
+ }
245
+ }
246
+
247
+ /**
248
+ */
249
+ public function registerStylesAndScripts() {
250
+ // register the stylesheet and javascript external resources
251
+ $pluginData = apply_filters ( 'postman_get_plugin_metadata', null );
252
+ wp_register_script ( 'postman_gmail_script', plugins_url ( 'Postman/Postman-Mail/postman_gmail.js', $this->rootPluginFilenameAndPath ), array (
253
+ PostmanViewController::JQUERY_SCRIPT,
254
+ 'jquery_validation',
255
+ PostmanViewController::POSTMAN_SCRIPT
256
+ ), $pluginData ['version'] );
257
+ }
258
+
259
+ /**
260
+ */
261
+ public function enqueueScript() {
262
+ wp_enqueue_script ( 'postman_gmail_script' );
263
+ }
264
+
265
+ /**
266
+ * Get Socket's logo
267
+ *
268
+ * @since 2.1
269
+ * @version 1.0
270
+ */
271
+ public function getLogoURL() {
272
+
273
+ return POST_SMTP_ASSETS . "images/logos/gmail.png";
274
+
275
+ }
276
+
277
+ /**
278
+ * Checks is granted or not
279
+ *
280
+ * @since 2.1.4
281
+ * @version 1.0
282
+ */
283
+ public function has_granted() {
284
+
285
+ if( $this->isPermissionNeeded() ) {
286
+ return false;
287
+ }
288
+
289
+ return true;
290
+
291
+ }
292
+
293
+ /**
294
+ * Returns the HTML of not granted
295
+ *
296
+ * @since 2.1.4
297
+ * @version 1.0
298
+ */
299
+ public function get_not_granted_notice() {
300
+
301
+ return array(
302
+ 'message' => __( ' You are just a step away to get started', 'post-smtp' ),
303
+ 'url_text' => $this->getScribe()->getRequestPermissionLinkText(),
304
+ 'url' => PostmanUtils::getGrantOAuthPermissionUrl()
305
+ );
306
+
307
+ }
308
+ }
Postman/Postman-Mail/PostmanGmailApiModuleZendMailTransport.php CHANGED
@@ -1,278 +1,278 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- /**
7
- * Zend Framework
8
- *
9
- * LICENSE
10
- *
11
- * This source file is subject to the new BSD license that is bundled
12
- * with this package in the file LICENSE.txt.
13
- * It is also available through the world-wide-web at this URL:
14
- * http://framework.zend.com/license/new-bsd
15
- * If you did not receive a copy of the license and are unable to
16
- * obtain it through the world-wide-web, please send an email
17
- * to license@zend.com so we can send you a copy immediately.
18
- *
19
- * @category Zend
20
- * @package Postman_Zend_Mail
21
- * @subpackage Transport
22
- * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
23
- * @license http://framework.zend.com/license/new-bsd New BSD License
24
- * @version $Id$
25
- */
26
-
27
- /**
28
- *
29
- * @see Postman_Zend_Mime
30
- */
31
- // require_once 'Zend/Mime.php';
32
-
33
- /**
34
- *
35
- * @see Postman_Zend_Mail_Protocol_Smtp
36
- */
37
- // require_once 'Zend/Mail/Protocol/Smtp.php';
38
-
39
- /**
40
- *
41
- * @see Postman_Zend_Mail_Transport_Abstract
42
- */
43
- // require_once 'Zend/Mail/Transport/Abstract.php';
44
-
45
- /**
46
- * SMTP connection object
47
- *
48
- * Loads an instance of Postman_Zend_Mail_Protocol_Smtp and forwards smtp transactions
49
- *
50
- * @category Zend
51
- * @package Postman_Zend_Mail
52
- * @subpackage Transport
53
- * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
54
- * @license http://framework.zend.com/license/new-bsd New BSD License
55
- */
56
- if (! class_exists ( 'PostmanGmailApiModuleZendMailTransport' )) {
57
- class PostmanGmailApiModuleZendMailTransport extends Postman_Zend_Mail_Transport_Abstract {
58
- const SERVICE_OPTION = 'service';
59
- const MESSAGE_SENDER_EMAIL_OPTION = 'sender_email';
60
- private $logger;
61
- private $message;
62
- private $transcript;
63
-
64
- /**
65
- * EOL character string used by transport
66
- *
67
- * @var string
68
- * @access public
69
- */
70
- public $EOL = "\n";
71
-
72
- /**
73
- * Remote smtp hostname or i.p.
74
- *
75
- * @var string
76
- */
77
- protected $_host;
78
-
79
- /**
80
- * Port number
81
- *
82
- * @var integer|null
83
- */
84
- protected $_port;
85
-
86
- /**
87
- * Local client hostname or i.p.
88
- *
89
- * @var string
90
- */
91
- protected $_name = 'localhost';
92
-
93
- /**
94
- * Authentication type OPTIONAL
95
- *
96
- * @var string
97
- */
98
- protected $_auth;
99
-
100
- /**
101
- * Config options for authentication
102
- *
103
- * @var array
104
- */
105
- protected $_config;
106
-
107
- /**
108
- * Instance of Postman_Zend_Mail_Protocol_Smtp
109
- *
110
- * @var Postman_Zend_Mail_Protocol_Smtp
111
- */
112
- protected $_connection;
113
-
114
- /**
115
- * Constructor.
116
- *
117
- * @param string $host
118
- * OPTIONAL (Default: 127.0.0.1)
119
- * @param array $config
120
- * OPTIONAL (Default: null)
121
- * @return void
122
- *
123
- * @todo Someone please make this compatible
124
- * with the SendMail transport class.
125
- */
126
- public function __construct($host = '127.0.0.1', Array $config = array()) {
127
- if (isset ( $config ['name'] )) {
128
- $this->_name = $config ['name'];
129
- }
130
- if (isset ( $config ['port'] )) {
131
- $this->_port = $config ['port'];
132
- }
133
- if (isset ( $config ['auth'] )) {
134
- $this->_auth = $config ['auth'];
135
- }
136
-
137
- $this->_host = $host;
138
- $this->_config = $config;
139
- $this->logger = new PostmanLogger ( get_class ( $this ) );
140
- }
141
-
142
- /**
143
- * Class destructor to ensure all open connections are closed
144
- *
145
- * @return void
146
- */
147
- public function __destruct() {
148
- if ($this->_connection instanceof Postman_Zend_Mail_Protocol_Smtp) {
149
- try {
150
- $this->_connection->quit ();
151
- } catch ( Postman_Zend_Mail_Protocol_Exception $e ) {
152
- // ignore
153
- }
154
- $this->_connection->disconnect ();
155
- }
156
- }
157
-
158
- /**
159
- * Sets the connection protocol instance
160
- *
161
- * @param Postman_Zend_Mail_Protocol_Abstract $client
162
- *
163
- * @return void
164
- */
165
- public function setConnection(Postman_Zend_Mail_Protocol_Abstract $connection) {
166
- $this->_connection = $connection;
167
- }
168
-
169
- /**
170
- * Gets the connection protocol instance
171
- *
172
- * @return Postman_Zend_Mail_Protocol_Abstract|null
173
- */
174
- public function getConnection() {
175
- return $this->_connection;
176
- }
177
-
178
- /**
179
- * Send an email via the Gmail API
180
- *
181
- * Uses URI https://www.googleapis.com
182
- *
183
- *
184
- * @return void
185
- * @todo Rename this to sendMail, it's a public method...
186
- */
187
- public function _sendMail() {
188
-
189
- // Prepare the message in message/rfc822
190
- $message = $this->header . Postman_Zend_Mime::LINEEND . $this->body;
191
- $this->message = $message;
192
-
193
- // The message needs to be encoded in Base64URL
194
- $encodedMessage = rtrim ( strtr ( base64_encode ( $message ), '+/', '-_' ), '=' );
195
- $googleApiMessage = new Google_Service_Gmail_Message ();
196
- $googleService = $this->_config [self::SERVICE_OPTION];
197
- $googleClient = $googleService->getClient();
198
-
199
- $file_size = strlen($message);
200
-
201
- $result = array ();
202
- try {
203
- $googleClient->setDefer(true);
204
- $result = $googleService->users_messages->send ( 'me', $googleApiMessage, array('uploadType' => 'resumable') );
205
-
206
- $chunkSizeBytes = 1 * 1024 * 1024;
207
-
208
- // create mediafile upload
209
- $media = new Google_Http_MediaFileUpload(
210
- $googleClient,
211
- $result,
212
- 'message/rfc822',
213
- $message,
214
- true,
215
- $chunkSizeBytes
216
- );
217
- $media->setFileSize($file_size);
218
-
219
- $status = false;
220
- while (! $status) {
221
- $status = $media->nextChunk();
222
- }
223
- $result = false;
224
-
225
- // Reset to the client to execute requests immediately in the future.
226
- $googleClient->setDefer(false);
227
-
228
- $googleMessageId = $status->getId();
229
-
230
- if ($this->logger->isInfo ()) {
231
- $this->logger->info ( sprintf ( 'Message %d accepted for delivery', PostmanState::getInstance ()->getSuccessfulDeliveries () + 1 ) );
232
- }
233
- $this->transcript = print_r ( $result, true );
234
- $this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
235
- $this->transcript .= $message;
236
- } catch ( Exception $e ) {
237
- $this->transcript = $e->getMessage ();
238
- $this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
239
- $this->transcript .= $message;
240
- throw $e;
241
- }
242
- }
243
-
244
- public function getMessage() {
245
- return $this->message;
246
- }
247
- public function getTranscript() {
248
- return $this->transcript;
249
- }
250
-
251
- /**
252
- * Format and fix headers
253
- *
254
- * Some SMTP servers do not strip BCC headers. Most clients do it themselves as do we.
255
- *
256
- * @access protected
257
- * @param array $headers
258
- * @return void
259
- * @throws Postman_Zend_Transport_Exception
260
- */
261
- protected function _prepareHeaders($headers) {
262
- if (! $this->_mail) {
263
- /**
264
- *
265
- * @see Postman_Zend_Mail_Transport_Exception
266
- */
267
- // require_once 'Zend/Mail/Transport/Exception.php';
268
- throw new Postman_Zend_Mail_Transport_Exception ( '_prepareHeaders requires a registered Postman_Zend_Mail object' );
269
- }
270
-
271
- // google will unset the Bcc header for us.
272
- // unset ( $headers ['Bcc'] );
273
-
274
- // Prepare headers
275
- parent::_prepareHeaders ( $headers );
276
- }
277
- }
278
  }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ /**
7
+ * Zend Framework
8
+ *
9
+ * LICENSE
10
+ *
11
+ * This source file is subject to the new BSD license that is bundled
12
+ * with this package in the file LICENSE.txt.
13
+ * It is also available through the world-wide-web at this URL:
14
+ * http://framework.zend.com/license/new-bsd
15
+ * If you did not receive a copy of the license and are unable to
16
+ * obtain it through the world-wide-web, please send an email
17
+ * to license@zend.com so we can send you a copy immediately.
18
+ *
19
+ * @category Zend
20
+ * @package Postman_Zend_Mail
21
+ * @subpackage Transport
22
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
23
+ * @license http://framework.zend.com/license/new-bsd New BSD License
24
+ * @version $Id$
25
+ */
26
+
27
+ /**
28
+ *
29
+ * @see Postman_Zend_Mime
30
+ */
31
+ // require_once 'Zend/Mime.php';
32
+
33
+ /**
34
+ *
35
+ * @see Postman_Zend_Mail_Protocol_Smtp
36
+ */
37
+ // require_once 'Zend/Mail/Protocol/Smtp.php';
38
+
39
+ /**
40
+ *
41
+ * @see Postman_Zend_Mail_Transport_Abstract
42
+ */
43
+ // require_once 'Zend/Mail/Transport/Abstract.php';
44
+
45
+ /**
46
+ * SMTP connection object
47
+ *
48
+ * Loads an instance of Postman_Zend_Mail_Protocol_Smtp and forwards smtp transactions
49
+ *
50
+ * @category Zend
51
+ * @package Postman_Zend_Mail
52
+ * @subpackage Transport
53
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
54
+ * @license http://framework.zend.com/license/new-bsd New BSD License
55
+ */
56
+ if (! class_exists ( 'PostmanGmailApiModuleZendMailTransport' )) {
57
+ class PostmanGmailApiModuleZendMailTransport extends Postman_Zend_Mail_Transport_Abstract {
58
+ const SERVICE_OPTION = 'service';
59
+ const MESSAGE_SENDER_EMAIL_OPTION = 'sender_email';
60
+ private $logger;
61
+ private $message;
62
+ private $transcript;
63
+
64
+ /**
65
+ * EOL character string used by transport
66
+ *
67
+ * @var string
68
+ * @access public
69
+ */
70
+ public $EOL = "\n";
71
+
72
+ /**
73
+ * Remote smtp hostname or i.p.
74
+ *
75
+ * @var string
76
+ */
77
+ protected $_host;
78
+
79
+ /**
80
+ * Port number
81
+ *
82
+ * @var integer|null
83
+ */
84
+ protected $_port;
85
+
86
+ /**
87
+ * Local client hostname or i.p.
88
+ *
89
+ * @var string
90
+ */
91
+ protected $_name = 'localhost';
92
+
93
+ /**
94
+ * Authentication type OPTIONAL
95
+ *
96
+ * @var string
97
+ */
98
+ protected $_auth;
99
+
100
+ /**
101
+ * Config options for authentication
102
+ *
103
+ * @var array
104
+ */
105
+ protected $_config;
106
+
107
+ /**
108
+ * Instance of Postman_Zend_Mail_Protocol_Smtp
109
+ *
110
+ * @var Postman_Zend_Mail_Protocol_Smtp
111
+ */
112
+ protected $_connection;
113
+
114
+ /**
115
+ * Constructor.
116
+ *
117
+ * @param string $host
118
+ * OPTIONAL (Default: 127.0.0.1)
119
+ * @param array $config
120
+ * OPTIONAL (Default: null)
121
+ * @return void
122
+ *
123
+ * @todo Someone please make this compatible
124
+ * with the SendMail transport class.
125
+ */
126
+ public function __construct($host = '127.0.0.1', Array $config = array()) {
127
+ if (isset ( $config ['name'] )) {
128
+ $this->_name = $config ['name'];
129
+ }
130
+ if (isset ( $config ['port'] )) {
131
+ $this->_port = $config ['port'];
132
+ }
133
+ if (isset ( $config ['auth'] )) {
134
+ $this->_auth = $config ['auth'];
135
+ }
136
+
137
+ $this->_host = $host;
138
+ $this->_config = $config;
139
+ $this->logger = new PostmanLogger ( get_class ( $this ) );
140
+ }
141
+
142
+ /**
143
+ * Class destructor to ensure all open connections are closed
144
+ *
145
+ * @return void
146
+ */
147
+ public function __destruct() {
148
+ if ($this->_connection instanceof Postman_Zend_Mail_Protocol_Smtp) {
149
+ try {
150
+ $this->_connection->quit ();
151
+ } catch ( Postman_Zend_Mail_Protocol_Exception $e ) {
152
+ // ignore
153
+ }
154
+ $this->_connection->disconnect ();
155
+ }
156
+ }
157
+
158
+ /**
159
+ * Sets the connection protocol instance
160
+ *
161
+ * @param Postman_Zend_Mail_Protocol_Abstract $client
162
+ *
163
+ * @return void
164
+ */
165
+ public function setConnection(Postman_Zend_Mail_Protocol_Abstract $connection) {
166
+ $this->_connection = $connection;
167
+ }
168
+
169
+ /**
170
+ * Gets the connection protocol instance
171
+ *
172
+ * @return Postman_Zend_Mail_Protocol_Abstract|null
173
+ */
174
+ public function getConnection() {
175
+ return $this->_connection;
176
+ }
177
+
178
+ /**
179
+ * Send an email via the Gmail API
180
+ *
181
+ * Uses URI https://www.googleapis.com
182
+ *
183
+ *
184
+ * @return void
185
+ * @todo Rename this to sendMail, it's a public method...
186
+ */
187
+ public function _sendMail() {
188
+
189
+ // Prepare the message in message/rfc822
190
+ $message = $this->header . Postman_Zend_Mime::LINEEND . $this->body;
191
+ $this->message = $message;
192
+
193
+ // The message needs to be encoded in Base64URL
194
+ $encodedMessage = rtrim ( strtr ( base64_encode ( $message ), '+/', '-_' ), '=' );
195
+ $googleApiMessage = new Google_Service_Gmail_Message ();
196
+ $googleService = $this->_config [self::SERVICE_OPTION];
197
+ $googleClient = $googleService->getClient();
198
+
199
+ $file_size = strlen($message);
200
+
201
+ $result = array ();
202
+ try {
203
+ $googleClient->setDefer(true);
204
+ $result = $googleService->users_messages->send ( 'me', $googleApiMessage, array('uploadType' => 'resumable') );
205
+
206
+ $chunkSizeBytes = 1 * 1024 * 1024;
207
+
208
+ // create mediafile upload
209
+ $media = new Google_Http_MediaFileUpload(
210
+ $googleClient,
211
+ $result,
212
+ 'message/rfc822',
213
+ $message,
214
+ true,
215
+ $chunkSizeBytes
216
+ );
217
+ $media->setFileSize($file_size);
218
+
219
+ $status = false;
220
+ while (! $status) {
221
+ $status = $media->nextChunk();
222
+ }
223
+ $result = false;
224
+
225
+ // Reset to the client to execute requests immediately in the future.
226
+ $googleClient->setDefer(false);
227
+
228
+ $googleMessageId = $status->getId();
229
+
230
+ if ($this->logger->isInfo ()) {
231
+ $this->logger->info ( sprintf ( 'Message %d accepted for delivery', PostmanState::getInstance ()->getSuccessfulDeliveries () + 1 ) );
232
+ }
233
+ $this->transcript = print_r ( $result, true );
234
+ $this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
235
+ $this->transcript .= $message;
236
+ } catch ( Exception $e ) {
237
+ $this->transcript = $e->getMessage ();
238
+ $this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
239
+ $this->transcript .= $message;
240
+ throw $e;
241
+ }
242
+ }
243
+
244
+ public function getMessage() {
245
+ return $this->message;
246
+ }
247
+ public function getTranscript() {
248
+ return $this->transcript;
249
+ }
250
+
251
+ /**
252
+ * Format and fix headers
253
+ *
254
+ * Some SMTP servers do not strip BCC headers. Most clients do it themselves as do we.
255
+ *
256
+ * @access protected
257
+ * @param array $headers
258
+ * @return void
259
+ * @throws Postman_Zend_Transport_Exception
260
+ */
261
+ protected function _prepareHeaders($headers) {
262
+ if (! $this->_mail) {
263
+ /**
264
+ *
265
+ * @see Postman_Zend_Mail_Transport_Exception
266
+ */
267
+ // require_once 'Zend/Mail/Transport/Exception.php';
268
+ throw new Postman_Zend_Mail_Transport_Exception ( '_prepareHeaders requires a registered Postman_Zend_Mail object' );
269
+ }
270
+
271
+ // google will unset the Bcc header for us.
272
+ // unset ( $headers ['Bcc'] );
273
+
274
+ // Prepare headers
275
+ parent::_prepareHeaders ( $headers );
276
+ }
277
+ }
278
  }
Postman/Postman-Mail/PostmanMailEngine.php CHANGED
@@ -1,14 +1,14 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- if (! interface_exists ( "PostmanMailEngine" )) {
7
-
8
- interface PostmanMailEngine {
9
- public function getTranscript();
10
- public function send(PostmanMessage $message);
11
- }
12
-
13
- }
14
-
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ if (! interface_exists ( "PostmanMailEngine" )) {
7
+
8
+ interface PostmanMailEngine {
9
+ public function getTranscript();
10
+ public function send(PostmanMessage $message);
11
+ }
12
+
13
+ }
14
+
Postman/Postman-Mail/PostmanMailgunMailEngine.php CHANGED
@@ -1,273 +1,273 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- require_once 'mailgun/mailgun.php';
7
-
8
- use Mailgun\Mailgun;
9
- use Mailgun\HttpClient\HttpClientConfigurator;
10
- use Mailgun\Hydrator\NoopHydrator;
11
-
12
-
13
- if ( ! class_exists( 'PostmanMailgunMailEngine' ) ) {
14
-
15
- /**
16
- * Sends mail with the SendGrid API
17
- * https://sendgrid.com/docs/API_Reference/Web_API/mail.html
18
- *
19
- * @author jasonhendriks
20
- */
21
- class PostmanMailgunMailEngine implements PostmanMailEngine {
22
-
23
- // logger for all concrete classes - populate with setLogger($logger)
24
- protected $logger;
25
-
26
- // the result
27
- private $transcript;
28
-
29
- private $api_endpoint;
30
- private $apiKey;
31
- private $domainName;
32
- private $mailgunMessage;
33
-
34
- /**
35
- *
36
- * @param mixed $senderEmail
37
- * @param mixed $accessToken
38
- */
39
- function __construct( $apiKey, $domainName ) {
40
- assert( ! empty( $apiKey ) );
41
- $this->apiKey = $apiKey;
42
- $this->domainName = $domainName;
43
-
44
- // create the logger
45
- $this->logger = new PostmanLogger( get_class( $this ) );
46
- $this->mailgunMessage = array(
47
- 'from' => '',
48
- 'to' => '',
49
- 'subject' => '',
50
- );
51
- }
52
-
53
- /**
54
- * (non-PHPdoc)
55
- *
56
- * @see PostmanSmtpEngine::send()
57
- */
58
- public function send( PostmanMessage $message ) {
59
- $options = PostmanOptions::getInstance();
60
- $this->api_endpoint = ! is_null( $options->getMailgunRegion() ) ? 'https://api.eu.mailgun.net' : 'https://api.mailgun.net';
61
-
62
- // add the Postman signature - append it to whatever the user may have set
63
- if ( ! $options->isStealthModeEnabled() ) {
64
- $pluginData = apply_filters( 'postman_get_plugin_metadata', null );
65
- $this->addHeader( 'X-Mailer', sprintf( 'Postman SMTP %s for WordPress (%s)', $pluginData ['version'], 'https://wordpress.org/plugins/post-smtp/' ) );
66
- }
67
-
68
- // add the headers - see http://framework.zend.com/manual/1.12/en/zend.mail.additional-headers.html
69
- foreach ( ( array ) $message->getHeaders() as $header ) {
70
- $this->logger->debug( sprintf( 'Adding user header %s=%s', $header ['name'], $header ['content'] ) );
71
- $this->addHeader( $header ['name'], $header ['content'], true );
72
- }
73
-
74
- // if the caller set a Content-Type header, use it
75
- $contentType = $message->getContentType();
76
- if ( ! empty( $contentType ) ) {
77
- $this->logger->debug( 'Adding content-type ' . $contentType );
78
- $this->addHeader( 'Content-Type', $contentType );
79
- }
80
-
81
- // add the From Header
82
- $sender = $message->getFromAddress();
83
- {
84
- $senderEmail = PostmanOptions::getInstance()->getMessageSenderEmail();
85
- $senderName = $sender->getName();
86
- assert( ! empty( $senderEmail ) );
87
-
88
- $senderText = ! empty( $senderName ) ? $senderName : $senderEmail;
89
- $this->mailgunMessage ['from'] = "{$senderText} <{$senderEmail}>";
90
- // now log it
91
- $sender->log( $this->logger, 'From' );
92
- }
93
-
94
- // add the Sender Header, overriding what the user may have set
95
- $this->addHeader( 'Sender', $options->getEnvelopeSender() );
96
-
97
- // add the to recipients
98
- $recipients = array();
99
- foreach ( ( array ) $message->getToRecipients() as $recipient ) {
100
- $recipient->log( $this->logger, 'To' );
101
- $recipients[] = $recipient->getEmail();
102
- }
103
- $this->mailgunMessage['to'] = $recipients;
104
-
105
- // add the cc recipients
106
- $recipients = array();
107
- foreach ( ( array ) $message->getCcRecipients() as $recipient ) {
108
- $recipient->log( $this->logger, 'Cc' );
109
- $recipients[] = $recipient->getEmail();
110
- }
111
- $this->mailgunMessage['cc'] = implode( ',', $recipients );
112
-
113
- // add the bcc recipients
114
- $recipients = array();
115
- foreach ( ( array ) $message->getBccRecipients() as $recipient ) {
116
- $recipient->log( $this->logger, 'Bcc' );
117
- $recipients[] = $recipient->getEmail();
118
- }
119
- $this->mailgunMessage['bcc'] = implode( ',', $recipients );
120
-
121
- // add the reply-to
122
- $replyTo = $message->getReplyTo();
123
- // $replyTo is null or a PostmanEmailAddress object
124
- if ( isset( $replyTo ) ) {
125
- $this->addHeader( 'reply-to', $replyTo->format() );
126
- }
127
-
128
- // add the date
129
- $date = $message->getDate();
130
- if ( ! empty( $date ) ) {
131
- $this->addHeader( 'date', $message->getDate() );
132
- }
133
-
134
- // add the messageId
135
- $messageId = $message->getMessageId();
136
- if ( ! empty( $messageId ) ) {
137
- $this->addHeader( 'message-id', $messageId );
138
- }
139
-
140
- // add the subject
141
- if ( null !== $message->getSubject() ) {
142
- $this->mailgunMessage ['subject'] = $message->getSubject();
143
- }
144
-
145
- // add the message content
146
- {
147
- $textPart = $message->getBodyTextPart();
148
- if ( ! empty( $textPart ) ) {
149
- $this->logger->debug( 'Adding body as text' );
150
- $this->mailgunMessage ['text'] = $textPart;
151
- }
152
- $htmlPart = $message->getBodyHtmlPart();
153
- if ( ! empty( $htmlPart ) ) {
154
- $this->logger->debug( 'Adding body as html' );
155
- $this->mailgunMessage ['html'] = $htmlPart;
156
- }
157
- }
158
-
159
- // add attachments
160
- $this->logger->debug( 'Adding attachments' );
161
- $this->addAttachmentsToMail( $message );
162
-
163
- $result = array();
164
- try {
165
- if ( $this->logger->isDebug() ) {
166
- $this->logger->debug( 'Creating Mailgun service with apiKey=' . $this->apiKey );
167
- }
168
-
169
- // send the message
170
- if ( $this->logger->isDebug() ) {
171
- $this->logger->debug( 'Sending mail' );
172
- }
173
-
174
- $configurator = new HttpClientConfigurator();
175
- $configurator->setEndpoint( $this->api_endpoint . '/v3/'. $this->domainName .'/messages');
176
- $configurator->setApiKey($this->apiKey);
177
- $mg = new Mailgun($configurator, new NoopHydrator());
178
-
179
- // Make the call to the client.
180
- $result = $this->processSend( $mg );
181
-
182
- if ( $this->logger->isInfo() ) {
183
- $this->logger->info( sprintf( 'Message %d accepted for delivery', PostmanState::getInstance()->getSuccessfulDeliveries() + 1 ) );
184
- }
185
-
186
- $this->transcript = print_r( $result, true );
187
- $this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
188
- $this->transcript .= print_r( $this->mailgunMessage, true );
189
- } catch ( Exception $e ) {
190
- $this->transcript = $e->getMessage();
191
- $this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
192
- $this->transcript .= print_r( $this->mailgunMessage, true );
193
- throw $e;
194
- }
195
- }
196
-
197
-
198
- private function processSend( $mg ) {
199
-
200
- if ( count( $this->mailgunMessage['to'] ) <= 1 ) {
201
-
202
- return $mg->messages()->send( $this->domainName, array_filter( $this->mailgunMessage ) );
203
- } else {
204
- $chunks = array_chunk( $this->mailgunMessage['to'], 1000, true );
205
-
206
- $result = array();
207
- foreach ( $chunks as $key => $emails ) {
208
- $this->mailgunMessage['to'] = $emails;
209
- $recipient_variables = $this->getRecipientVariables( $emails );
210
- $this->mailgunMessage['recipient-variables'] = $recipient_variables;
211
-
212
- $result[] = $mg->messages()->send( $this->domainName, array_filter( $this->mailgunMessage ) );
213
-
214
- // Don't have a reason just wait a bit before sending the next chunk
215
- sleep(2);
216
- }
217
-
218
- return $result;
219
- }
220
- }
221
-
222
- private function getRecipientVariables( $emails ) {
223
- $recipient_variables = array();
224
- foreach ( $emails as $key => $email ) {
225
- $recipient_variables[$email] = array( 'id' => $key );
226
- }
227
-
228
- return json_encode( $recipient_variables );
229
- }
230
-
231
- private function addHeader( $name, $value, $deprecated = '' ) {
232
- if ( $value && ! empty( $value ) ) {
233
- $this->mailgunMessage['h:' . $name] = preg_replace('/.*:\s?/', '', $value);
234
- }
235
- }
236
-
237
- /**
238
- * Add attachments to the message
239
- *
240
- * @param Postman_Zend_Mail $mail
241
- */
242
- private function addAttachmentsToMail( PostmanMessage $message ) {
243
- $attachments = $message->getAttachments();
244
- if ( ! is_array( $attachments ) ) {
245
- // WordPress may a single filename or a newline-delimited string list of multiple filenames
246
- $attArray[] = explode( PHP_EOL, $attachments );
247
- } else {
248
- $attArray = $attachments;
249
- }
250
-
251
- $attachments = array();
252
- foreach ( $attArray as $file ) {
253
- if ( ! empty( $file ) ) {
254
- $this->logger->debug( 'Adding attachment: ' . $file );
255
- $attachments[] = array( 'filePath' => $file );
256
- }
257
- }
258
-
259
- if ( ! empty( $attachments ) ) {
260
- if ( $this->logger->isTrace() ) {
261
- $this->logger->trace( $attachments );
262
- }
263
- $this->mailgunMessage['attachment'] = $attachments;
264
- }
265
- }
266
-
267
- // return the SMTP session transcript
268
- public function getTranscript() {
269
- return $this->transcript;
270
- }
271
- }
272
- }
273
-
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ require_once 'mailgun/mailgun.php';
7
+
8
+ use Mailgun\Mailgun;
9
+ use Mailgun\HttpClient\HttpClientConfigurator;
10
+ use Mailgun\Hydrator\NoopHydrator;
11
+
12
+
13
+ if ( ! class_exists( 'PostmanMailgunMailEngine' ) ) {
14
+
15
+ /**
16
+ * Sends mail with the SendGrid API
17
+ * https://sendgrid.com/docs/API_Reference/Web_API/mail.html
18
+ *
19
+ * @author jasonhendriks
20
+ */
21
+ class PostmanMailgunMailEngine implements PostmanMailEngine {
22
+
23
+ // logger for all concrete classes - populate with setLogger($logger)
24
+ protected $logger;
25
+
26
+ // the result
27
+ private $transcript;
28
+
29
+ private $api_endpoint;
30
+ private $apiKey;
31
+ private $domainName;
32
+ private $mailgunMessage;
33
+
34
+ /**
35
+ *
36
+ * @param mixed $senderEmail
37
+ * @param mixed $accessToken
38
+ */
39
+ function __construct( $apiKey, $domainName ) {
40
+ assert( ! empty( $apiKey ) );
41
+ $this->apiKey = $apiKey;
42
+ $this->domainName = $domainName;
43
+
44
+ // create the logger
45
+ $this->logger = new PostmanLogger( get_class( $this ) );
46
+ $this->mailgunMessage = array(
47
+ 'from' => '',
48
+ 'to' => '',
49
+ 'subject' => '',
50
+ );
51
+ }
52
+
53
+ /**
54
+ * (non-PHPdoc)
55
+ *
56
+ * @see PostmanSmtpEngine::send()
57
+ */
58
+ public function send( PostmanMessage $message ) {
59
+ $options = PostmanOptions::getInstance();
60
+ $this->api_endpoint = ! is_null( $options->getMailgunRegion() ) ? 'https://api.eu.mailgun.net' : 'https://api.mailgun.net';
61
+
62
+ // add the Postman signature - append it to whatever the user may have set
63
+ if ( ! $options->isStealthModeEnabled() ) {
64
+ $pluginData = apply_filters( 'postman_get_plugin_metadata', null );
65
+ $this->addHeader( 'X-Mailer', sprintf( 'Postman SMTP %s for WordPress (%s)', $pluginData ['version'], 'https://wordpress.org/plugins/post-smtp/' ) );
66
+ }
67
+
68
+ // add the headers - see http://framework.zend.com/manual/1.12/en/zend.mail.additional-headers.html
69
+ foreach ( ( array ) $message->getHeaders() as $header ) {
70
+ $this->logger->debug( sprintf( 'Adding user header %s=%s', $header ['name'], $header ['content'] ) );
71
+ $this->addHeader( $header ['name'], $header ['content'], true );
72
+ }
73
+
74
+ // if the caller set a Content-Type header, use it
75
+ $contentType = $message->getContentType();
76
+ if ( ! empty( $contentType ) ) {
77
+ $this->logger->debug( 'Adding content-type ' . $contentType );
78
+ $this->addHeader( 'Content-Type', $contentType );
79
+ }
80
+
81
+ // add the From Header
82
+ $sender = $message->getFromAddress();
83
+ {
84
+ $senderEmail = PostmanOptions::getInstance()->getMessageSenderEmail();
85
+ $senderName = $sender->getName();
86
+ assert( ! empty( $senderEmail ) );
87
+
88
+ $senderText = ! empty( $senderName ) ? $senderName : $senderEmail;
89
+ $this->mailgunMessage ['from'] = "{$senderText} <{$senderEmail}>";
90
+ // now log it
91
+ $sender->log( $this->logger, 'From' );
92
+ }
93
+
94
+ // add the Sender Header, overriding what the user may have set
95
+ $this->addHeader( 'Sender', $options->getEnvelopeSender() );
96
+
97
+ // add the to recipients
98
+ $recipients = array();
99
+ foreach ( ( array ) $message->getToRecipients() as $recipient ) {
100
+ $recipient->log( $this->logger, 'To' );
101
+ $recipients[] = $recipient->getEmail();
102
+ }
103
+ $this->mailgunMessage['to'] = $recipients;
104
+
105
+ // add the cc recipients
106
+ $recipients = array();
107
+ foreach ( ( array ) $message->getCcRecipients() as $recipient ) {
108
+ $recipient->log( $this->logger, 'Cc' );
109
+ $recipients[] = $recipient->getEmail();
110
+ }
111
+ $this->mailgunMessage['cc'] = implode( ',', $recipients );
112
+
113
+ // add the bcc recipients
114
+ $recipients = array();
115
+ foreach ( ( array ) $message->getBccRecipients() as $recipient ) {
116
+ $recipient->log( $this->logger, 'Bcc' );
117
+ $recipients[] = $recipient->getEmail();
118
+ }
119
+ $this->mailgunMessage['bcc'] = implode( ',', $recipients );
120
+
121
+ // add the reply-to
122
+ $replyTo = $message->getReplyTo();
123
+ // $replyTo is null or a PostmanEmailAddress object
124
+ if ( isset( $replyTo ) ) {
125
+ $this->addHeader( 'reply-to', $replyTo->format() );
126
+ }
127
+
128
+ // add the date
129
+ $date = $message->getDate();
130
+ if ( ! empty( $date ) ) {
131
+ $this->addHeader( 'date', $message->getDate() );
132
+ }
133
+
134
+ // add the messageId
135
+ $messageId = $message->getMessageId();
136
+ if ( ! empty( $messageId ) ) {
137
+ $this->addHeader( 'message-id', $messageId );
138
+ }
139
+
140
+ // add the subject
141
+ if ( null !== $message->getSubject() ) {
142
+ $this->mailgunMessage ['subject'] = $message->getSubject();
143
+ }
144
+
145
+ // add the message content
146
+ {
147
+ $textPart = $message->getBodyTextPart();
148
+ if ( ! empty( $textPart ) ) {
149
+ $this->logger->debug( 'Adding body as text' );
150
+ $this->mailgunMessage ['text'] = $textPart;
151
+ }
152
+ $htmlPart = $message->getBodyHtmlPart();
153
+ if ( ! empty( $htmlPart ) ) {
154
+ $this->logger->debug( 'Adding body as html' );
155
+ $this->mailgunMessage ['html'] = $htmlPart;
156
+ }
157
+ }
158
+
159
+ // add attachments
160
+ $this->logger->debug( 'Adding attachments' );
161
+ $this->addAttachmentsToMail( $message );
162
+
163
+ $result = array();
164
+ try {
165
+ if ( $this->logger->isDebug() ) {
166
+ $this->logger->debug( 'Creating Mailgun service with apiKey=' . $this->apiKey );
167
+ }
168
+
169
+ // send the message
170
+ if ( $this->logger->isDebug() ) {
171
+ $this->logger->debug( 'Sending mail' );
172
+ }
173
+
174
+ $configurator = new HttpClientConfigurator();
175
+ $configurator->setEndpoint( $this->api_endpoint . '/v3/'. $this->domainName .'/messages');
176
+ $configurator->setApiKey($this->apiKey);
177
+ $mg = new Mailgun($configurator, new NoopHydrator());
178
+
179
+ // Make the call to the client.
180
+ $result = $this->processSend( $mg );
181
+
182
+ if ( $this->logger->isInfo() ) {
183
+ $this->logger->info( sprintf( 'Message %d accepted for delivery', PostmanState::getInstance()->getSuccessfulDeliveries() + 1 ) );
184
+ }
185
+
186
+ $this->transcript = print_r( $result, true );
187
+ $this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
188
+ $this->transcript .= print_r( $this->mailgunMessage, true );
189
+ } catch ( Exception $e ) {
190
+ $this->transcript = $e->getMessage();
191
+ $this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
192
+ $this->transcript .= print_r( $this->mailgunMessage, true );
193
+ throw $e;
194
+ }
195
+ }
196
+
197
+
198
+ private function processSend( $mg ) {
199
+
200
+ if ( count( $this->mailgunMessage['to'] ) <= 1 ) {
201
+
202
+ return $mg->messages()->send( $this->domainName, array_filter( $this->mailgunMessage ) );
203
+ } else {
204
+ $chunks = array_chunk( $this->mailgunMessage['to'], 1000, true );
205
+
206
+ $result = array();
207
+ foreach ( $chunks as $key => $emails ) {
208
+ $this->mailgunMessage['to'] = $emails;
209
+ $recipient_variables = $this->getRecipientVariables( $emails );
210
+ $this->mailgunMessage['recipient-variables'] = $recipient_variables;
211
+
212
+ $result[] = $mg->messages()->send( $this->domainName, array_filter( $this->mailgunMessage ) );
213
+
214
+ // Don't have a reason just wait a bit before sending the next chunk
215
+ sleep(2);
216
+ }
217
+
218
+ return $result;
219
+ }
220
+ }
221
+
222
+ private function getRecipientVariables( $emails ) {
223
+ $recipient_variables = array();
224
+ foreach ( $emails as $key => $email ) {
225
+ $recipient_variables[$email] = array( 'id' => $key );
226
+ }
227
+
228
+ return json_encode( $recipient_variables );
229
+ }
230
+
231
+ private function addHeader( $name, $value, $deprecated = '' ) {
232
+ if ( $value && ! empty( $value ) ) {
233
+ $this->mailgunMessage['h:' . $name] = preg_replace('/.*:\s?/', '', $value);
234
+ }
235
+ }
236
+
237
+ /**
238
+ * Add attachments to the message
239
+ *
240
+ * @param Postman_Zend_Mail $mail
241
+ */
242
+ private function addAttachmentsToMail( PostmanMessage $message ) {
243
+ $attachments = $message->getAttachments();
244
+ if ( ! is_array( $attachments ) ) {
245
+ // WordPress may a single filename or a newline-delimited string list of multiple filenames
246
+ $attArray[] = explode( PHP_EOL, $attachments );
247
+ } else {
248
+ $attArray = $attachments;
249
+ }
250
+
251
+ $attachments = array();
252
+ foreach ( $attArray as $file ) {
253
+ if ( ! empty( $file ) ) {
254
+ $this->logger->debug( 'Adding attachment: ' . $file );
255
+ $attachments[] = array( 'filePath' => $file );
256
+ }
257
+ }
258
+
259
+ if ( ! empty( $attachments ) ) {
260
+ if ( $this->logger->isTrace() ) {
261
+ $this->logger->trace( $attachments );
262
+ }
263
+ $this->mailgunMessage['attachment'] = $attachments;
264
+ }
265
+ }
266
+
267
+ // return the SMTP session transcript
268
+ public function getTranscript() {
269
+ return $this->transcript;
270
+ }
271
+ }
272
+ }
273
+
Postman/Postman-Mail/PostmanMailgunTransport.php CHANGED
@@ -1,293 +1,293 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- require_once 'PostmanModuleTransport.php';
7
- /**
8
- * Postman Mailgun module
9
- *
10
- * @author jasonhendriks
11
- */
12
- class PostmanMailgunTransport extends PostmanAbstractModuleTransport implements PostmanModuleTransport {
13
- const SLUG = 'mailgun_api';
14
- const PORT = 443;
15
- const HOST = 'api.mailgun.net';
16
- const EU_REGION = 'api.eu.mailgun.net';
17
- const PRIORITY = 8000;
18
- const MAILGUN_AUTH_OPTIONS = 'postman_mailgun_auth_options';
19
- const MAILGUN_AUTH_SECTION = 'postman_mailgun_auth_section';
20
-
21
- /**
22
- *
23
- * @param mixed $rootPluginFilenameAndPath
24
- */
25
- public function __construct( $rootPluginFilenameAndPath ) {
26
- parent::__construct( $rootPluginFilenameAndPath );
27
-
28
- // add a hook on the plugins_loaded event
29
- add_action( 'admin_init', array(
30
- $this,
31
- 'on_admin_init',
32
- ) );
33
- }
34
- public function getProtocol() {
35
- return 'https';
36
- }
37
-
38
- // this should be standard across all transports
39
- public function getSlug() {
40
- return self::SLUG;
41
- }
42
- public function getName() {
43
- return __( 'Mailgun API', 'post-smtp' );
44
- }
45
- /**
46
- * v0.2.1
47
- *
48
- * @return string
49
- */
50
- public function getHostname() {
51
- return ! is_null( $this->options->getMailgunRegion() ) ? self::EU_REGION : self::HOST;
52
- }
53
- /**
54
- * v0.2.1
55
- *
56
- * @return int
57
- */
58
- public function getPort() {
59
- return self::PORT;
60
- }
61
- /**
62
- * v1.7.0
63
- *
64
- * @return string
65
- */
66
- public function getTransportType() {
67
- return 'Mailgun_api';
68
- }
69
-
70
- /**
71
- * (non-PHPdoc)
72
- *
73
- * @see PostmanModuleTransport::createMailEngine()
74
- */
75
- public function createMailEngine() {
76
- $apiKey = $this->options->getMailgunApiKey();
77
- $domainName = $this->options->getMailgunDomainName();
78
-
79
- require_once 'PostmanMailgunMailEngine.php';
80
- $engine = new PostmanMailgunMailEngine( $apiKey, $domainName );
81
- return $engine;
82
- }
83
- public function getDeliveryDetails() {
84
- /* translators: where (1) is the secure icon and (2) is the transport name */
85
- return sprintf( __( 'Post SMTP will send mail via the <b>%1$s %2$s</b>.', 'post-smtp' ), '🔐', $this->getName() );
86
- }
87
-
88
- /**
89
- *
90
- * @param mixed $data
91
- */
92
- public function prepareOptionsForExport( $data ) {
93
- $data = parent::prepareOptionsForExport( $data );
94
- $data [ PostmanOptions::MAILGUN_API_KEY ] = PostmanOptions::getInstance()->getMailgunApiKey();
95
- return $data;
96
- }
97
-
98
- /**
99
- * (non-PHPdoc)
100
- *
101
- * @see PostmanTransport::getMisconfigurationMessage()
102
- */
103
- protected function validateTransportConfiguration() {
104
- $messages = parent::validateTransportConfiguration();
105
- $apiKey = $this->options->getMailgunApiKey();
106
- $domainName = $this->options->getMailgunDomainName();
107
-
108
- if ( empty( $apiKey ) ) {
109
- array_push( $messages, __( 'API Key can not be empty', 'post-smtp' ) . '.' );
110
- $this->setNotConfiguredAndReady();
111
- }
112
-
113
- if ( empty( $domainName ) ) {
114
- array_push( $messages, __( 'Domain Name can not be empty', 'post-smtp' ) . '.' );
115
- $this->setNotConfiguredAndReady();
116
- }
117
-
118
- if ( ! $this->isSenderConfigured() ) {
119
- array_push( $messages, __( 'Message From Address can not be empty', 'post-smtp' ) . '.' );
120
- $this->setNotConfiguredAndReady();
121
- }
122
- return $messages;
123
- }
124
-
125
- /**
126
- * (non-PHPdoc)
127
- *
128
- * @see PostmanModuleTransport::getConfigurationBid()
129
- */
130
- public function getConfigurationBid( PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer ) {
131
- $recommendation = array();
132
- $recommendation ['priority'] = 0;
133
- $recommendation ['transport'] = self::SLUG;
134
- $recommendation ['hostname'] = null; // scribe looks this
135
- $recommendation ['label'] = $this->getName();
136
- $recommendation['logo_url'] = $this->getLogoURL();
137
-
138
- if ( $hostData->hostname == $this->getHostname() && $hostData->port == self::PORT ) {
139
- $recommendation ['priority'] = self::PRIORITY;
140
- /* translators: where variables are (1) transport name (2) host and (3) port */
141
- $recommendation ['message'] = sprintf( __( ('Postman recommends the %1$s to host %2$s on port %3$d.') ), $this->getName(), $this->getHostname(), self::PORT );
142
- }
143
- return $recommendation;
144
- }
145
-
146
- /**
147
- *
148
- * @param mixed $hostname
149
- * @param mixed $response
150
- */
151
- public function populateConfiguration( $hostname ) {
152
- $response = parent::populateConfiguration( $hostname );
153
- return $response;
154
- }
155
-
156
- /**
157
- */
158
- public function createOverrideMenu( PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride ) {
159
- $overrideItem = parent::createOverrideMenu( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
160
- // push the authentication options into the $overrideItem structure
161
- $overrideItem ['auth_items'] = array(
162
- array(
163
- 'selected' => true,
164
- 'name' => __( 'API Key', 'post-smtp' ),
165
- 'value' => 'api_key',
166
- ),
167
- );
168
- return $overrideItem;
169
- }
170
-
171
- /**
172
- * Functions to execute on the admin_init event
173
- *
174
- * "Runs at the beginning of every admin page before the page is rendered."
175
- * ref: http://codex.wordpress.org/Plugin_API/Action_Reference#Actions_Run_During_an_Admin_Page_Request
176
- */
177
- public function on_admin_init() {
178
- // only administrators should be able to trigger this
179
- if ( PostmanUtils::isAdmin() ) {
180
- $this->addSettings();
181
- $this->registerStylesAndScripts();
182
- }
183
- }
184
-
185
- /*
186
- * What follows in the code responsible for creating the Admin Settings page
187
- */
188
-
189
- /**
190
- */
191
- public function addSettings() {
192
- // the Mailgun Auth section
193
- add_settings_section( PostmanMailgunTransport::MAILGUN_AUTH_SECTION, __( 'Authentication', 'post-smtp' ), array(
194
- $this,
195
- 'printMailgunAuthSectionInfo',
196
- ), PostmanMailgunTransport::MAILGUN_AUTH_OPTIONS );
197
-
198
- add_settings_field( PostmanOptions::MAILGUN_API_KEY, __( 'API Key', 'post-smtp' ), array(
199
- $this,
200
- 'mailgun_api_key_callback',
201
- ), PostmanMailgunTransport::MAILGUN_AUTH_OPTIONS, PostmanMailgunTransport::MAILGUN_AUTH_SECTION );
202
-
203
- add_settings_field( PostmanOptions::MAILGUN_DOMAIN_NAME, __( 'Domain Name', 'post-smtp' ), array(
204
- $this,
205
- 'mailgun_domain_name_callback',
206
- ), PostmanMailgunTransport::MAILGUN_AUTH_OPTIONS, PostmanMailgunTransport::MAILGUN_AUTH_SECTION );
207
-
208
- add_settings_field( PostmanOptions::MAILGUN_REGION, __( 'Mailgun Europe Region?', 'post-smtp' ), array(
209
- $this,
210
- 'mailgun_region_callback',
211
- ), PostmanMailgunTransport::MAILGUN_AUTH_OPTIONS, PostmanMailgunTransport::MAILGUN_AUTH_SECTION );
212
- }
213
- public function printMailgunAuthSectionInfo() {
214
- /* Translators: Where (1) is the service URL and (2) is the service name and (3) is a api key URL */
215
- printf( '<p id="wizard_mailgun_auth_help">%s</p>', sprintf( __( 'Create an account at <a href="%1$s" target="_blank">%2$s</a> and enter <a href="%3$s" target="_blank">an API key</a> below.', 'post-smtp' ), 'https://mailgun.com', 'mailgun.com', 'https://app.mailgun.com/app/domains/' ) );
216
- }
217
-
218
- /**
219
- */
220
- public function mailgun_api_key_callback() {
221
- printf( '<input type="password" autocomplete="off" id="mailgun_api_key" name="postman_options[mailgun_api_key]" value="%s" size="60" class="required ps-input ps-w-75" placeholder="%s"/>', null !== $this->options->getMailgunApiKey() ? esc_attr( PostmanUtils::obfuscatePassword( $this->options->getMailgunApiKey() ) ) : '', __( 'Required', 'post-smtp' ) );
222
- print '<input type="button" id="toggleMailgunApiKey" value="Show Password" class="button button-secondary" style="visibility:hidden" />';
223
- }
224
-
225
- function mailgun_domain_name_callback() {
226
- printf( '<input type="text" autocomplete="off" id="mailgun_domain_name" name="postman_options[mailgun_domain_name]" value="%s" size="60" class="required ps-input ps-w-75" placeholder="%s"/>', null !== $this->options->getMailgunDomainName() ? esc_attr( $this->options->getMailgunDomainName() ) : '', __( 'Required', 'post-smtp' ) );
227
- }
228
-
229
- function mailgun_region_callback() {
230
- $value = $this->options->getMailgunRegion();
231
- printf( '<input type="checkbox" id="mailgun_region" name="postman_options[mailgun_region]"%s />', null !== $value ? ' checked' : '' );
232
- }
233
-
234
- /**
235
- */
236
- public function registerStylesAndScripts() {
237
- // register the stylesheet and javascript external resources
238
- $pluginData = apply_filters( 'postman_get_plugin_metadata', null );
239
- wp_register_script( 'postman_mailgun_script', plugins_url( 'Postman/Postman-Mail/postman_mailgun.js', $this->rootPluginFilenameAndPath ), array(
240
- PostmanViewController::JQUERY_SCRIPT,
241
- 'jquery_validation',
242
- PostmanViewController::POSTMAN_SCRIPT,
243
- ), $pluginData ['version'] );
244
- }
245
-
246
- /**
247
- */
248
- public function enqueueScript() {
249
- wp_enqueue_script( 'postman_mailgun_script' );
250
- }
251
-
252
- /**
253
- */
254
- public function printWizardAuthenticationStep() {
255
- print '<section class="wizard_mailgun">';
256
- $this->printMailgunAuthSectionInfo();
257
- printf( '<label for="api_key">%s</label>', __( 'API Key', 'post-smtp' ) );
258
- print '<br />';
259
- print $this->mailgun_api_key_callback();
260
- printf( '<label for="domain_name">%s</label>', __( 'Domain Name', 'post-smtp' ) );
261
- print '<br />';
262
- print $this->mailgun_domain_name_callback();
263
- print '<br />';
264
- printf( '<label for="mailgun_region">%s</label>', __( 'Mailgun Europe Region?', 'post-smtp' ) );
265
- print '<br />';
266
- print $this->mailgun_region_callback();
267
- print '</section>';
268
- }
269
-
270
- /**
271
- * Get Socket's logo
272
- *
273
- * @since 2.1
274
- * @version 1.0
275
- */
276
- public function getLogoURL() {
277
-
278
- return POST_SMTP_ASSETS . "images/logos/mailgun.png";
279
-
280
- }
281
-
282
- /**
283
- * Returns true, to prevent from errors because it's default Module Transport.
284
- *
285
- * @since 2.1.8
286
- * @version 1.0
287
- */
288
- public function has_granted() {
289
-
290
- return true;
291
-
292
- }
293
- }
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ exit; // Exit if accessed directly
4
+ }
5
+
6
+ require_once 'PostmanModuleTransport.php';
7
+ /**
8
+ * Postman Mailgun module
9
+ *
10
+ * @author jasonhendriks
11
+ */
12
+ class PostmanMailgunTransport extends PostmanAbstractModuleTransport implements PostmanModuleTransport {
13
+ const SLUG = 'mailgun_api';
14
+ const PORT = 443;
15
+ const HOST = 'api.mailgun.net';
16
+ const EU_REGION = 'api.eu.mailgun.net';
17
+ const PRIORITY = 8000;
18
+ const MAILGUN_AUTH_OPTIONS = 'postman_mailgun_auth_options';
19
+ const MAILGUN_AUTH_SECTION = 'postman_mailgun_auth_section';
20
+
21
+ /**
22
+ *
23
+ * @param mixed $rootPluginFilenameAndPath
24
+ */
25
+ public function __construct( $rootPluginFilenameAndPath ) {
26
+ parent::__construct( $rootPluginFilenameAndPath );
27
+
28
+ // add a hook on the plugins_loaded event
29
+ add_action( 'admin_init', array(
30
+ $this,
31
+ 'on_admin_init',
32
+ ) );
33
+ }
34
+ public function getProtocol() {
35
+ return 'https';
36
+ }
37
+
38
+ // this should be standard across all transports
39
+ public function getSlug() {
40
+ return self::SLUG;
41
+ }
42
+ public function getName() {
43
+ return __( 'Mailgun API', 'post-smtp' );
44
+ }
45
+ /**
46
+ * v0.2.1
47
+ *
48
+ * @return string
49
+ */
50
+ public function getHostname() {
51
+ return ! is_null( $this->options->getMailgunRegion() ) ? self::EU_REGION : self::HOST;
52
+ }
53
+ /**
54
+ * v0.2.1
55
+ *
56
+ * @return int
57
+ */
58
+ public function getPort() {
59
+ return self::PORT;
60
+ }
61
+ /**
62
+ * v1.7.0
63
+ *
64
+ * @return string
65
+ */
66
+ public function getTransportType() {
67
+ return 'Mailgun_api';
68
+ }
69
+
70
+ /**
71
+ * (non-PHPdoc)
72
+ *
73
+ * @see PostmanModuleTransport::createMailEngine()
74
+ */
75
+ public function createMailEngine() {
76
+ $apiKey = $this->options->getMailgunApiKey();
77
+ $domainName = $this->options->getMailgunDomainName();
78
+
79
+ require_once 'PostmanMailgunMailEngine.php';
80
+ $engine = new PostmanMailgunMailEngine( $apiKey, $domainName );
81
+ return $engine;
82
+ }
83
+ public function getDeliveryDetails() {
84
+ /* translators: where (1) is the secure icon and (2) is the transport name */
85
+ return sprintf( __( 'Post SMTP will send mail via the <b>%1$s %2$s</b>.', 'post-smtp' ), '🔐', $this->getName() );
86
+ }
87
+
88
+ /**
89
+ *
90
+ * @param mixed $data
91
+ */
92
+ public function prepareOptionsForExport( $data ) {
93
+ $data = parent::prepareOptionsForExport( $data );
94
+ $data [ PostmanOptions::MAILGUN_API_KEY ] = PostmanOptions::getInstance()->getMailgunApiKey();
95
+ return $data;
96
+ }
97
+
98
+ /**
99
+ * (non-PHPdoc)
100
+ *
101
+ * @see PostmanTransport::getMisconfigurationMessage()
102
+ */
103
+ protected function validateTransportConfiguration() {
104
+ $messages = parent::validateTransportConfiguration();
105
+ $apiKey = $this->options->getMailgunApiKey();
106
+ $domainName = $this->options->getMailgunDomainName();
107
+
108
+ if ( empty( $apiKey ) ) {
109
+ array_push( $messages, __( 'API Key can not be empty', 'post-smtp' ) . '.' );
110
+ $this->setNotConfiguredAndReady();
111
+ }
112
+
113
+ if ( empty( $domainName ) ) {
114
+ array_push( $messages, __( 'Domain Name can not be empty', 'post-smtp' ) . '.' );
115
+ $this->setNotConfiguredAndReady();
116
+ }
117
+
118
+ if ( ! $this->isSenderConfigured() ) {
119
+ array_push( $messages, __( 'Message From Address can not be empty', 'post-smtp' ) . '.' );
120
+ $this->setNotConfiguredAndReady();
121
+ }
122
+ return $messages;
123
+ }
124
+
125
+ /**
126
+ * (non-PHPdoc)
127
+ *
128
+ * @see PostmanModuleTransport::getConfigurationBid()
129
+ */
130
+ public function getConfigurationBid( PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer ) {
131
+ $recommendation = array();
132
+ $recommendation ['priority'] = 0;
133
+ $recommendation ['transport'] = self::SLUG;
134
+ $recommendation ['hostname'] = null; // scribe looks this
135
+ $recommendation ['label'] = $this->getName();
136
+ $recommendation['logo_url'] = $this->getLogoURL();
137
+
138
+ if ( $hostData->hostname == $this->getHostname() && $hostData->port == self::PORT ) {
139
+ $recommendation ['priority'] = self::PRIORITY;
140
+ /* translators: where variables are (1) transport name (2) host and (3) port */
141
+ $recommendation ['message'] = sprintf( __( ('Postman recommends the %1$s to host %2$s on port %3$d.') ), $this->getName(), $this->getHostname(), self::PORT );
142
+ }
143
+ return $recommendation;
144
+ }
145
+
146
+ /**
147
+ *
148
+ * @param mixed $hostname
149
+ * @param mixed $response
150
+ */
151
+ public function populateConfiguration( $hostname ) {
152
+ $response = parent::populateConfiguration( $hostname );
153
+ return $response;
154
+ }
155
+
156
+ /**
157
+ */
158
+ public function createOverrideMenu( PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride ) {
159
+ $overrideItem = parent::createOverrideMenu( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
160
+ // push the authentication options into the $overrideItem structure
161
+ $overrideItem ['auth_items'] = array(
162
+ array(
163
+ 'selected' => true,
164
+ 'name' => __( 'API Key', 'post-smtp' ),
165
+ 'value' => 'api_key',
166
+ ),
167
+ );
168
+ return $overrideItem;
169
+ }
170
+
171
+ /**
172
+ * Functions to execute on the admin_init event
173
+ *
174
+ * "Runs at the beginning of every admin page before the page is rendered."
175
+ * ref: http://codex.wordpress.org/Plugin_API/Action_Reference#Actions_Run_During_an_Admin_Page_Request
176
+ */
177
+ public function on_admin_init() {
178
+ // only administrators should be able to trigger this
179
+ if ( PostmanUtils::isAdmin() ) {
180
+ $this->addSettings();
181
+ $this->registerStylesAndScripts();
182
+ }
183
+ }
184
+
185
+ /*
186
+ * What follows in the code responsible for creating the Admin Settings page
187
+ */
188
+
189
+ /**
190
+ */
191
+ public function addSettings() {
192
+ // the Mailgun Auth section
193
+ add_settings_section( PostmanMailgunTransport::MAILGUN_AUTH_SECTION, __( 'Authentication', 'post-smtp' ), array(
194
+ $this,
195
+ 'printMailgunAuthSectionInfo',
196
+ ), PostmanMailgunTransport::MAILGUN_AUTH_OPTIONS );
197
+
198
+ add_settings_field( PostmanOptions::MAILGUN_API_KEY, __( 'API Key', 'post-smtp' ), array(
199
+ $this,
200
+ 'mailgun_api_key_callback',
201
+ ), PostmanMailgunTransport::MAILGUN_AUTH_OPTIONS, PostmanMailgunTransport::MAILGUN_AUTH_SECTION );
202
+
203
+ add_settings_field( PostmanOptions::MAILGUN_DOMAIN_NAME, __( 'Domain Name', 'post-smtp' ), array(
204
+ $this,
205
+ 'mailgun_domain_name_callback',
206
+ ), PostmanMailgunTransport::MAILGUN_AUTH_OPTIONS, PostmanMailgunTransport::MAILGUN_AUTH_SECTION );
207
+
208
+ add_settings_field( PostmanOptions::MAILGUN_REGION, __( 'Mailgun Europe Region?', 'post-smtp' ), array(
209
+ $this,
210
+ 'mailgun_region_callback',
211
+ ), PostmanMailgunTransport::MAILGUN_AUTH_OPTIONS, PostmanMailgunTransport::MAILGUN_AUTH_SECTION );
212
+ }
213
+ public function printMailgunAuthSectionInfo() {
214
+ /* Translators: Where (1) is the service URL and (2) is the service name and (3) is a api key URL */
215
+ printf( '<p id="wizard_mailgun_auth_help">%s</p>', sprintf( __( 'Create an account at <a href="%1$s" target="_blank">%2$s</a> and enter <a href="%3$s" target="_blank">an API key</a> below.', 'post-smtp' ), 'https://mailgun.com', 'mailgun.com', 'https://app.mailgun.com/app/domains/' ) );
216
+ }
217
+
218
+ /**
219
+ */
220
+ public function mailgun_api_key_callback() {
221
+ printf( '<input type="password" autocomplete="off" id="mailgun_api_key" name="postman_options[mailgun_api_key]" value="%s" size="60" class="required ps-input ps-w-75" placeholder="%s"/>', null !== $this->options->getMailgunApiKey() ? esc_attr( PostmanUtils::obfuscatePassword( $this->options->getMailgunApiKey() ) ) : '', __( 'Required', 'post-smtp' ) );
222
+ print '<input type="button" id="toggleMailgunApiKey" value="Show Password" class="button button-secondary" style="visibility:hidden" />';
223
+ }
224
+
225
+ function mailgun_domain_name_callback() {
226
+ printf( '<input type="text" autocomplete="off" id="mailgun_domain_name" name="postman_options[mailgun_domain_name]" value="%s" size="60" class="required ps-input ps-w-75" placeholder="%s"/>', null !== $this->options->getMailgunDomainName() ? esc_attr( $this->options->getMailgunDomainName() ) : '', __( 'Required', 'post-smtp' ) );
227
+ }
228
+
229
+ function mailgun_region_callback() {
230
+ $value = $this->options->getMailgunRegion();
231
+ printf( '<input type="checkbox" id="mailgun_region" name="postman_options[mailgun_region]"%s />', null !== $value ? ' checked' : '' );
232
+ }
233
+
234
+ /**
235
+ */
236
+ public function registerStylesAndScripts() {
237
+ // register the stylesheet and javascript external resources
238
+ $pluginData = apply_filters( 'postman_get_plugin_metadata', null );
239
+ wp_register_script( 'postman_mailgun_script', plugins_url( 'Postman/Postman-Mail/postman_mailgun.js', $this->rootPluginFilenameAndPath ), array(
240
+ PostmanViewController::JQUERY_SCRIPT,
241
+ 'jquery_validation',
242
+ PostmanViewController::POSTMAN_SCRIPT,
243
+ ), $pluginData ['version'] );
244
+ }
245
+
246
+ /**
247
+ */
248
+ public function enqueueScript() {
249
+ wp_enqueue_script( 'postman_mailgun_script' );
250
+ }
251
+
252
+ /**
253
+ */
254
+ public function printWizardAuthenticationStep() {
255
+ print '<section class="wizard_mailgun">';
256
+ $this->printMailgunAuthSectionInfo();
257
+ printf( '<label for="api_key">%s</label>', __( 'API Key', 'post-smtp' ) );
258
+ print '<br />';
259
+ print $this->mailgun_api_key_callback();
260
+ printf( '<label for="domain_name">%s</label>', __( 'Domain Name', 'post-smtp' ) );
261
+ print '<br />';
262
+ print $this->mailgun_domain_name_callback();
263
+ print '<br />';
264
+ printf( '<label for="mailgun_region">%s</label>', __( 'Mailgun Europe Region?', 'post-smtp' ) );
265
+ print '<br />';
266
+ print $this->mailgun_region_callback();
267
+ print '</section>';
268
+ }
269
+
270
+ /**
271
+ * Get Socket's logo
272
+ *
273
+ * @since 2.1
274
+ * @version 1.0
275
+ */
276
+ public function getLogoURL() {
277
+
278
+ return POST_SMTP_ASSETS . "images/logos/mailgun.png";
279
+
280
+ }
281
+
282
+ /**
283
+ * Returns true, to prevent from errors because it's default Module Transport.
284
+ *
285
+ * @since 2.1.8
286
+ * @version 1.0
287
+ */
288
+ public function has_granted() {
289
+
290
+ return true;
291
+
292
+ }
293
+ }
Postman/Postman-Mail/PostmanMandrillMailEngine.php CHANGED
@@ -1,238 +1,238 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit; // Exit if accessed directly
4
- }
5
-
6
- if ( ! class_exists( 'PostmanMandrillMailEngine' ) ) {
7
-
8
- require_once 'mailchimp-mandrill-api-php-da3adc10042e/src/Mandrill.php';
9
-
10
- /**
11
- * Sends mail with Mandrill API
12
- * https://mandrillapp.com/api/docs/messages.php.html
13
- *
14
- * @author jasonhendriks
15
- */
16
- class PostmanMandrillMailEngine implements PostmanMailEngine {
17
-
18
- // logger for all concrete classes - populate with setLogger($logger)
19
- protected $logger;
20
-
21
- // the result
22
- private $transcript;
23
-
24
- private $apiKey;
25
- private $mandrillMessage;
26
-
27
- /**
28
- *
29
- * @param mixed $senderEmail
30
- * @param mixed $accessToken
31
- */
32
- function __construct( $apiKey ) {
33
- assert( ! empty( $apiKey ) );
34
- $this->apiKey = $apiKey;
35
-
36
- // create the logger
37
- $this->logger = new PostmanLogger( get_class( $this ) );
38
-
39
- // create the Message
40
- $this->mandrillMessage = array(
41
- 'to' => array(),
42
- 'headers' => array(),
43
- );
44
- }
45
-
46
- /**
47
- * (non-PHPdoc)
48
- *
49
- * @see PostmanSmtpEngine::send()
50
- */
51
- public function send( PostmanMessage $message ) {
52
- $options = PostmanOptions::getInstance();
53
-
54
- // add the Postman signature - append it to whatever the user may have set
55
- if ( ! $options->isStealthModeEnabled() ) {
56
- $pluginData = apply_filters( 'postman_get_plugin_metadata', null );
57
- $this->addHeader( 'X-Mailer', sprintf( 'Postman SMTP %s for WordPress (%s)', $pluginData ['version'], 'https://wordpress.org/plugins/post-smtp/' ) );
58
- }
59
-
60
- // add the headers - see http://framework.zend.com/manual/1.12/en/zend.mail.additional-headers.html
61
- foreach ( ( array ) $message->getHeaders() as $header ) {
62
- $this->logger->debug( sprintf( 'Adding user header %s=%s', $header ['name'], $header ['content'] ) );
63
- $this->addHeader( $header ['name'], $header ['content'], true );
64
- }
65
-
66
- // if the caller set a Content-Type header, use it
67
- $contentType = $message->getContentType();
68
- if ( ! empty( $contentType ) ) {
69
- $this->logger->debug( 'Adding content-type ' . $contentType );
70
- $this->addHeader( 'Content-Type', $contentType );
71
- }
72
-
73
- // add the From Header
74
- $sender = $message->getFromAddress();
75
- {
76
- $senderEmail = PostmanOptions::getInstance()->getMessageSenderEmail();
77
- $senderName = $sender->getName();
78
- assert( ! empty( $senderEmail ) );
79
- $this->mandrillMessage ['from_email'] = $senderEmail;
80
- if ( ! empty( $senderName ) ) {
81
- $this->mandrillMessage ['from_name'] = $senderName;
82
- }
83
- // now log it
84
- $sender->log( $this->logger, 'From' );
85
- }
86
-
87
- // add the Sender Header, overriding what the user may have set
88
- $this->addHeader( 'Sender', $options->getEnvelopeSender() );
89
-
90
- // add the to recipients
91
- foreach ( ( array ) $message->getToRecipients() as $recipient ) {
92
- $recipient->log( $this->logger, 'To' );
93
- $recipient = array(
94
- 'email' => $recipient->getEmail(),
95
- 'name' => $recipient->getName(),
96
- 'type' => 'to',
97
- );
98
- array_push( $this->mandrillMessage ['to'], $recipient );
99
- }
100
-
101
- // add the cc recipients
102
- foreach ( ( array ) $message->getCcRecipients() as $recipient ) {
103
- $recipient->log( $this->logger, 'Cc' );
104
- $recipient = array(
105
- 'email' => $recipient->getEmail(),
106
- 'name' => $recipient->getName(),
107
- 'type' => 'cc',
108
- );
109
- array_push( $this->mandrillMessage ['to'], $recipient );
110
- }
111
-
112
- // add the bcc recipients
113
- foreach ( ( array ) $message->getBccRecipients() as $recipient ) {
114
- $recipient->log( $this->logger, 'Bcc' );
115
- $recipient = array(
116
- 'email' => $recipient->getEmail(),
117
- 'name' => $recipient->getName(),
118
- 'type' => 'bcc',
119
- );
120
- array_push( $this->mandrillMessage ['to'], $recipient );
121
- }
122
-
123
- // add the reply-to
124
- $replyTo = $message->getReplyTo();
125
- // $replyTo is null or a PostmanEmailAddress object
126
- if ( isset( $replyTo ) ) {
127
- $this->addHeader( 'reply-to', $replyTo->format() );
128
- }
129
-
130
- // add the date
131
- $date = $message->getDate();
132
- if ( ! empty( $date ) ) {
133
- $this->addHeader( 'date', $message->getDate() );
134
- }
135
-
136
- // add the messageId
137
- $messageId = $message->getMessageId();
138
- if ( ! empty( $messageId ) ) {
139
- $this->addHeader( 'message-id', $messageId );
140
- }
141
-
142
- // add the subject
143
- if ( null !== $message->getSubject() ) {
144
- $this->mandrillMessage ['subject'] = $message->getSubject();
145
- }
146
-
147
- // add the message content
148
- {
149
- $textPart = $message->getBodyTextPart();
150
- if ( ! empty( $textPart ) ) {
151
- $this->logger->debug( 'Adding body as text' );
152
- $this->mandrillMessage ['text'] = $textPart;
153
- }
154
- $htmlPart = $message->getBodyHtmlPart();
155
- if ( ! empty( $htmlPart ) ) {
156
- $this->logger->debug( 'Adding body as html' );
157
- $this->mandrillMessage ['html'] = $htmlPart;
158
- }
159
- }
160
-
161
- // add attachments
162
- $this->logger->debug( 'Adding attachments' );
163
- $this->addAttachmentsToMail( $message );
164
-
165
- $result = array();
166
- try {
167
- if ( $this->logger->isDebug() ) {
168
- $this->logger->debug( 'Creating Mandrill service with apiKey=' . $this->apiKey );
169
- }
170
- $mandrill = new Postman_Mandrill( $this->apiKey );
171
-
172
- // send the message
173
- if ( $this->logger->isDebug() ) {
174
- $this->logger->debug( 'Sending mail' );
175
- }
176
-
177
- $result = $mandrill->messages->send( $this->mandrillMessage );
178
- if ( $this->logger->isInfo() ) {
179
- $this->logger->info( sprintf( 'Message %d accepted for delivery', PostmanState::getInstance()->getSuccessfulDeliveries() + 1 ) );
180
- }
181
-
182
- $this->transcript = print_r( $result, true );
183
- $this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
184
- $this->transcript .= print_r( $this->mandrillMessage, true );
185
- } catch ( Exception $e ) {
186
- $this->transcript = $e->getMessage();
187
- $this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
188
- $this->transcript .= print_r( $this->mandrillMessage, true );
189
- throw $e;
190
- }
191
- }
192
- private functi