@@ -295,6 +295,26 @@ public function add_new_options( $new_ver, $old_ver ): void {
295
295
296
296
update_option ( 'no-unsafe-inline ' , $ options );
297
297
}
298
+ if ( version_compare ( $ old_ver , '1.2.3 ' , '< ' ) ) {
299
+ $ options = (array ) get_option ( 'no-unsafe-inline ' );
300
+ if ( isset ( $ options ['endpoints ' ] ) &&
301
+ Utils::is_one_dimensional_string_array ( $ options ['endpoints ' ] )
302
+ ) {
303
+ $ new_endpoint = array ();
304
+ foreach ( $ options ['endpoints ' ] as $ index => $ endpoint ) {
305
+ $ new_endpoint [] = array (
306
+ 'url ' => $ endpoint ,
307
+ 'name ' => 'csp-endpoint- ' . strval ( $ index ),
308
+ );
309
+ }
310
+ $ options ['endpoints ' ] = $ new_endpoint ;
311
+ }
312
+ if ( isset ( $ options ['use_reports ' ] ) && 1 === $ options ['use_reports ' ] ) {
313
+ $ options ['use_report-to ' ] = 1 ;
314
+ $ options ['add_Reporting-Endpoints ' ] = 1 ;
315
+ }
316
+ update_option ( 'no-unsafe-inline ' , $ options );
317
+ }
298
318
}
299
319
300
320
/**
@@ -767,6 +787,77 @@ public function register_options(): void {
767
787
'no-unsafe-inline_report '
768
788
);
769
789
790
+ add_settings_field (
791
+ 'use_report-to ' ,
792
+ sprintf (
793
+ // translators: %1$s is report-uri link.
794
+ esc_html__ ( 'Use %1$s reporting directive ' , 'no-unsafe-inline ' ),
795
+ '<a href="https://www.w3.org/TR/CSP3/#directive-report-to" target="_blank">report-to</a> '
796
+ ),
797
+ array ( $ this , 'print_toggle_option ' ),
798
+ 'no-unsafe-inline-options ' ,
799
+ 'no-unsafe-inline_report ' ,
800
+ array (
801
+ 'option_name ' => 'use_report-to ' ,
802
+ 'label ' => __ ( 'Use the report-to directive to send reports to a URI. ' , 'no-unsafe-inline ' ),
803
+ )
804
+ );
805
+
806
+ add_settings_field (
807
+ 'use_report-uri ' ,
808
+ sprintf (
809
+ // translators: %1$s is report-uri link.
810
+ esc_html__ ( 'Use %1$s reporting directive (deprecated) ' , 'no-unsafe-inline ' ),
811
+ '<a href="https://www.w3.org/TR/CSP3/#directive-report-uri" target="_blank">report-uri</a> '
812
+ ),
813
+ array ( $ this , 'print_toggle_option ' ),
814
+ 'no-unsafe-inline-options ' ,
815
+ 'no-unsafe-inline_report ' ,
816
+ array (
817
+ 'option_name ' => 'use_report-uri ' ,
818
+ 'label ' => __ ( 'Use the report-uri directive to send reports to a URI. ' , 'no-unsafe-inline ' ),
819
+ )
820
+ );
821
+
822
+ add_settings_field (
823
+ 'add_Reporting-Endpoints ' ,
824
+ sprintf (
825
+ // translators: %1$s is report-uri link.
826
+ esc_html__ ( 'Add the %1$s response header field to define the reporting endpoints. ' , 'no-unsafe-inline ' ),
827
+ '<a href="https://www.w3.org/TR/reporting-1/#header" target="_blank">Reporting-Endpoints</a> '
828
+ ),
829
+ array ( $ this , 'print_toggle_option ' ),
830
+ 'no-unsafe-inline-options ' ,
831
+ 'no-unsafe-inline_report ' ,
832
+ array (
833
+ 'option_name ' => 'add_Reporting-Endpoints ' ,
834
+ 'label ' => esc_html__ ( 'Add the Reporting-Endpoints response header field to define a set of reporting endpoints for a document or a worker script. ' , 'no-unsafe-inline ' ) .
835
+ '<br> ' . __ ( 'This is a standard feature included in the Reporting API v1. ' , 'no-unsafe-inline ' ),
836
+ )
837
+ );
838
+
839
+ add_settings_field (
840
+ 'add_Report-To ' ,
841
+ sprintf (
842
+ // translators: %1$s is report-uri link.
843
+ esc_html__ ( 'Add the %1$s response header field to define the reporting endpoints (legacy and deprecated) ' , 'no-unsafe-inline ' ),
844
+ '<a href="https://www.w3.org/TR/2016/NOTE-reporting-1-20160607/#header" target="_blank">Report-To</a> '
845
+ ),
846
+ array ( $ this , 'print_toggle_option ' ),
847
+ 'no-unsafe-inline-options ' ,
848
+ 'no-unsafe-inline_report ' ,
849
+ array (
850
+ 'option_name ' => 'add_Report-To ' ,
851
+ 'label ' => sprintf (
852
+ __ ( 'Add the Report-To response header field to instruct the user agent to store a reporting endpoints for an origin. ' , 'no-unsafe-inline ' ) .
853
+ '<br> ' . __ ( 'This is a legacy and deprecated feature, never standardized and included in the Reporting API v0. ' , 'no-unsafe-inline ' ) .
854
+ // translators: %s is a link.
855
+ '<br> ' . __ ( 'See %s. ' , 'no-unsafe-inline ' ),
856
+ '<a href="https://developer.chrome.com/blog/reporting-api-migration" target="_blank">Migrate to Reporting API v1</a> '
857
+ ),
858
+ )
859
+ );
860
+
770
861
add_settings_field (
771
862
'group_name ' ,
772
863
esc_html__ ( 'Group name ' , 'no-unsafe-inline ' ),
@@ -946,8 +1037,12 @@ public function register_base_rule(): void {
946
1037
/**
947
1038
* Sanitize the settings
948
1039
*
1040
+ * The returned array is the sanitized settings and should be in the format:
1041
+ * array<string, string|int|array<int, array{url: string, name: string}>>
1042
+ * Using mixed, because get_option() returns mixed and we need to merge it with array.
1043
+ *
949
1044
* @throws \NUNIL\Nunil_Exception Main option is not an array.
950
- * @param array<string|int|array<int|string> > $input Contains the settings.
1045
+ * @param array<mixed > $input Contains the settings.
951
1046
* @return array<mixed>
952
1047
*/
953
1048
public function sanitize_options ( $ input ) {
@@ -981,6 +1076,10 @@ public function sanitize_options( $input ) {
981
1076
'fix_setattribute_style ' ,
982
1077
'add_wl_by_cluster_to_db ' ,
983
1078
'use_reports ' ,
1079
+ 'use_report-to ' ,
1080
+ 'use_report-uri ' ,
1081
+ 'add_Reporting-Endpoints ' ,
1082
+ 'add_Report-To ' ,
984
1083
'remove_tables ' ,
985
1084
'remove_options '
986
1085
);
@@ -1100,14 +1199,33 @@ public function sanitize_options( $input ) {
1100
1199
}
1101
1200
}
1102
1201
1103
- unset( $ options ['endpoints ' ] );
1104
1202
if ( isset ( $ input ['endpoints ' ] ) && is_array ( $ input ['endpoints ' ] ) ) {
1105
1203
$ new_input ['endpoints ' ] = array_map (
1106
- function ( $ url ) {
1107
- return esc_url_raw ( strval ( $ url ), array ( 'https ' ) );
1204
+ function ( $ endpoint ) {
1205
+ /**
1206
+ * Since trustworthy depends on user agent, we shouldnt' limit to https only.
1207
+ * However almost all browsers consider only https as trustworthy to deply a report.
1208
+ *
1209
+ * See: https://w3c.github.io/reporting/#header
1210
+ * See: https://w3c.github.io/webappsec-secure-contexts/#is-origin-trustworthy
1211
+ */
1212
+ if (
1213
+ is_array ( $ endpoint ) &&
1214
+ array_key_exists ( 'url ' , $ endpoint ) &&
1215
+ array_key_exists ( 'name ' , $ endpoint ) &&
1216
+ $ this ->is_trustworthy_url ( Utils::sanitize_text ( $ endpoint ['url ' ], false ) )
1217
+ ) {
1218
+ return array (
1219
+ 'url ' => esc_url_raw ( Utils::sanitize_text ( $ endpoint ['url ' ], false ) ),
1220
+ 'name ' => Utils::sanitize_text ( $ endpoint ['name ' ], false ),
1221
+ );
1222
+ }
1223
+ return null ;
1108
1224
},
1109
1225
$ input ['endpoints ' ]
1110
1226
);
1227
+ // resetto da 0 le chiavi dell'array e elimino eventuali valori nulli.
1228
+ $ new_input ['endpoints ' ] = array_values ( array_filter ( $ new_input ['endpoints ' ] ) );
1111
1229
}
1112
1230
1113
1231
if ( isset ( $ input ['max_response_header_size ' ] ) ) {
@@ -1126,6 +1244,43 @@ function ( $url ) {
1126
1244
return $ new_options ;
1127
1245
}
1128
1246
1247
+ /**
1248
+ * Check if a URL is trustworthy.
1249
+ *
1250
+ * @param string $url_string The URL to check.
1251
+ * @return bool True if the URL is trustworthy, false otherwise.
1252
+ */
1253
+ private function is_trustworthy_url ( $ url_string ) {
1254
+ if ( empty ( $ url_string ) ) {
1255
+ return false ;
1256
+ }
1257
+
1258
+ // Sanitize the URL.
1259
+ $ url_string = esc_url_raw ( $ url_string );
1260
+
1261
+ // Parse the URL.
1262
+ $ url = wp_parse_url ( $ url_string );
1263
+
1264
+ if ( false === $ url ) {
1265
+ return false ;
1266
+ }
1267
+
1268
+ // Check if the protocol is https.
1269
+ if ( isset ( $ url ['scheme ' ] ) && 'https ' === $ url ['scheme ' ] ) {
1270
+ return true ;
1271
+ }
1272
+
1273
+ // Check if the host matches 127.0.0.0/8 or ::1/128 .
1274
+ if ( isset ( $ url ['host ' ] ) ) {
1275
+ $ host = $ url ['host ' ];
1276
+ if ( 'localhost ' === $ host || '127.0.0.1 ' === $ host || '::1 ' === $ host ) {
1277
+ return true ;
1278
+ }
1279
+ }
1280
+
1281
+ return false ;
1282
+ }
1283
+
1129
1284
/**
1130
1285
* Sanitize the tools status
1131
1286
*
@@ -1696,38 +1851,76 @@ public function print_endpoints(): void {
1696
1851
1697
1852
// Add new endpoint button.
1698
1853
printf (
1854
+ '<div><b> ' .
1855
+ esc_html__ ( 'Required. An array of JSON objects that specify the actual URL of your report collector. ' , 'no-unsafe-inline ' ) .
1856
+ '</b></div> '
1857
+ );
1858
+ printf (
1859
+ '<div class="nunil-new-endpoint-container"> ' .
1860
+ '<div class="nunil-new-endpoint-button-wrapper"> ' .
1699
1861
'<input class="nunil-btn nunil-btn-addnew" type="button" id="no-unsafe-inline[add_new_endpoint]" ' .
1700
1862
'name="no-unsafe-inline[add_new_endpoint]" value="%s" %s /> ' .
1863
+ '</div> ' .
1864
+ '<div class="nunil-new-endpoint-url-wrapper"> ' .
1865
+ '<label for="no-unsafe-inline[new_endpoint]" class="nunil_label_left">%s</label> ' .
1701
1866
'<input class="nunil-new-endpoint" type="text" id="no-unsafe-inline[new_endpoint]" ' .
1702
- 'name="no-unsafe-inline[new_endpoint]" %s />
1703
- <label for="no-unsafe-inline[new_endpoint]">%s</label> ' ,
1867
+ 'name="no-unsafe-inline[new_endpoint]" %s /> ' .
1868
+ '</div> ' .
1869
+ '<div class="nunil-new-endpoint-name-wrapper"> ' .
1870
+ '<label for="no-unsafe-inline[new_endpoint_name]" class="nunil_label_left">%s</label> ' .
1871
+ '<input class="nunil-new-endpoint-name" type="text" id="no-unsafe-inline[new_endpoint_name]" ' .
1872
+ 'name="no-unsafe-inline[new_endpoint_name]" %s /> ' .
1873
+ '</div> ' .
1874
+ '</div> ' ,
1704
1875
esc_html__ ( 'Add a new endpoint ' , 'no-unsafe-inline ' ),
1705
1876
esc_html ( $ disabled ),
1877
+ esc_html__ ( 'endpoint URL ' , 'no-unsafe-inline ' ) . ': ' ,
1878
+ esc_html ( $ disabled ),
1879
+ esc_html__ ( 'endpoint name ' , 'no-unsafe-inline ' ) . ': ' ,
1706
1880
esc_html ( $ disabled ),
1707
- esc_html__ ( 'Required. An array of JSON objects that specify the actual URL of your report collector. ' , 'no-unsafe-inline ' )
1708
1881
);
1709
1882
1710
1883
print ( '<ol class="nunil-endpoints-list" id="nunil-endpoints-list"> ' );
1711
- // Add a line for each url.
1712
- foreach ( $ endpoints as $ index => $ endpoint ) {
1713
- $ endp_txt = strval ( Utils::cast_strval ( $ endpoint ) );
1884
+ if ( count ( $ endpoints ) > 0 ) {
1885
+ // Add a header line.
1714
1886
printf (
1715
- '<li> ' .
1716
- '<button class="nunil-btn nunil-btn-del-endpoint" ' .
1717
- 'id="no-unsafe-inline[del-endpoint][%d]" name="no-unsafe-inline[del-endpoint][%d]"> ' .
1718
- '<span class="dashicons dashicons-remove"> </span></button> ' .
1719
- '<span class="nunil-endpoint-string txt-active">%s</span> ' .
1720
- '<input class="nunil-hidden-endpoint" type="hidden" id="no-unsafe-inline[endpoints][%d]" ' .
1721
- 'name="no-unsafe-inline[endpoints][%d]" value="%s" /> ' .
1722
- '</li> ' ,
1723
- esc_html ( $ index ),
1724
- esc_html ( $ index ),
1725
- esc_html ( $ endp_txt ),
1726
- esc_html ( $ index ),
1727
- esc_html ( $ index ),
1728
- esc_html ( $ endp_txt )
1887
+ '<li><span class="nunil-btn nunil-btn-endpoint-list" disabled><span class="dashicons dashicons-editor-ul"></span></span> ' .
1888
+ '<span class="nunil-endpoint-string"><b>%s</b></span> ' .
1889
+ '<span class="nunil-endpoint-string"><b>%s</b></span></li> ' ,
1890
+ esc_html__ ( 'endpoint URL ' , 'no-unsafe-inline ' ),
1891
+ esc_html__ ( 'endpoint name ' , 'no-unsafe-inline ' )
1729
1892
);
1730
1893
}
1894
+ // Add a line for each url.
1895
+ foreach ( $ endpoints as $ index => $ endpoint ) {
1896
+ if ( is_array ( $ endpoint ) && array_key_exists ( 'url ' , $ endpoint ) && array_key_exists ( 'name ' , $ endpoint ) ) {
1897
+ $ endp_url = strval ( Utils::cast_strval ( $ endpoint ['url ' ] ) );
1898
+ $ endp_name = strval ( Utils::cast_strval ( $ endpoint ['name ' ] ) );
1899
+ printf (
1900
+ '<li> ' .
1901
+ '<button class="nunil-btn nunil-btn-del-endpoint" ' .
1902
+ 'id="no-unsafe-inline[del-endpoint][%d]" name="no-unsafe-inline[del-endpoint][%d]"> ' .
1903
+ '<span class="dashicons dashicons-remove"> </span></button> ' .
1904
+ '<span class="nunil-endpoint-string txt-active">%s</span> ' .
1905
+ '<input class="nunil-hidden-endpoint" type="hidden" id="no-unsafe-inline[endpoints][%d][url]" ' .
1906
+ 'name="no-unsafe-inline[endpoints][%d][url]" value="%s" /> ' .
1907
+ '<span class="nunil-endpoint-string txt-active">%s</span> ' .
1908
+ '<input class="nunil-hidden-endpoint" type="hidden" id="no-unsafe-inline[endpoints][%d][name]" ' .
1909
+ 'name="no-unsafe-inline[endpoints][%d][name]" value="%s" /> ' .
1910
+ '</li> ' ,
1911
+ esc_html ( $ index ),
1912
+ esc_html ( $ index ),
1913
+ esc_html ( $ endp_url ),
1914
+ esc_html ( $ index ),
1915
+ esc_html ( $ index ),
1916
+ esc_html ( $ endp_url ),
1917
+ esc_html ( $ endp_name ),
1918
+ esc_html ( $ index ),
1919
+ esc_html ( $ index ),
1920
+ esc_html ( $ endp_name ),
1921
+ );
1922
+ }
1923
+ }
1731
1924
print ( '</ol> ' );
1732
1925
}
1733
1926
0 commit comments