Gentoo Archives: gentoo-commits

From: Theo Chatzimichos <tampakrap@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/blogs-gentoo:master commit in: plugins/jetpack/modules/contact-form/, plugins/jetpack/modules/contact-form/css/, ...
Date: Thu, 01 Aug 2013 07:04:05
Message-Id: 1375340778.2d6f7d9cd4baee8c303942220506ef756208145f.tampakrap@gentoo
1 commit: 2d6f7d9cd4baee8c303942220506ef756208145f
2 Author: Theo Chatzimichos <tampakrap <AT> gentoo <DOT> org>
3 AuthorDate: Thu Aug 1 07:06:18 2013 +0000
4 Commit: Theo Chatzimichos <tampakrap <AT> gentoo <DOT> org>
5 CommitDate: Thu Aug 1 07:06:18 2013 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/blogs-gentoo.git;a=commit;h=2d6f7d9c
7
8 forgot to include new files of jetpack
9
10 ---
11 plugins/jetpack/_inc/genericons.css | 149 +
12 .../class.jetpack-bbpress-json-api-compat.php | 108 +
13 plugins/jetpack/class.jetpack-client-server.php | 219 ++
14 plugins/jetpack/class.jetpack-client.php | 215 ++
15 plugins/jetpack/class.jetpack-data.php | 42 +
16 plugins/jetpack/class.jetpack-debugger.php | 353 ++
17 plugins/jetpack/class.jetpack-error.php | 3 +
18 plugins/jetpack/class.jetpack-heartbeat.php | 131 +
19 plugins/jetpack/class.jetpack-options.php | 143 +
20 plugins/jetpack/class.jetpack-sync.php | 713 ++++
21 plugins/jetpack/class.jetpack.php | 3684 ++++++++++++++++++++
22 plugins/jetpack/languages/jetpack-uk.mo | Bin 0 -> 9961 bytes
23 .../modules/contact-form/css/menu-alter.css | 56 +
24 .../modules/contact-form/css/rtl/grunion-rtl.css | 12 +
25 .../contact-form/css/rtl/menu-alter-rtl.css | 62 +
26 .../modules/contact-form/grunion-omnisearch.php | 65 +
27 .../modules/contact-form/js/grunion-frontend.js | 3 +
28 .../modules/custom-css/custom-css/css/ace.css | 25 +
29 .../custom-css/custom-css/css/css-editor.css | 24 +
30 .../custom-css/custom-css/js/ace/mode-less.js | 1 +
31 .../custom-css/custom-css/js/ace/mode-scss.js | 1 +
32 .../modules/custom-css/custom-css/js/css-editor.js | 81 +
33 .../infinite-scroll/themes/twentythirteen.css | 90 +
34 .../infinite-scroll/themes/twentythirteen.php | 26 +
35 plugins/jetpack/modules/likes/post-count.js | 69 +
36 .../inc/fonts/genericons-regular-webfont.eot | Bin 0 -> 7475 bytes
37 .../inc/fonts/genericons-regular-webfont.svg | 81 +
38 .../inc/fonts/genericons-regular-webfont.ttf | Bin 0 -> 13516 bytes
39 .../inc/fonts/genericons-regular-webfont.woff | Bin 0 -> 8676 bytes
40 plugins/jetpack/modules/omnisearch.php | 14 +
41 .../modules/omnisearch/omnisearch-comments.php | 48 +
42 .../jetpack/modules/omnisearch/omnisearch-core.php | 181 +
43 .../modules/omnisearch/omnisearch-jetpack.css | 35 +
44 .../modules/omnisearch/omnisearch-plugins.php | 61 +
45 .../modules/omnisearch/omnisearch-posts.php | 122 +
46 plugins/jetpack/modules/omnisearch/omnisearch.css | 126 +
47 .../omnisearch/rtl/omnisearch-jetpack-rtl.css | 37 +
48 .../modules/omnisearch/rtl/omnisearch-rtl.css | 128 +
49 .../jetpack/modules/sharedaddy/images/kindle.png | Bin 0 -> 1843 bytes
50 .../modules/sharedaddy/images/kindle@××.png | Bin 0 -> 1563 bytes
51 .../jetpack/modules/sharedaddy/images/pocket.png | Bin 0 -> 1288 bytes
52 .../modules/sharedaddy/images/pocket@××.png | Bin 0 -> 1425 bytes
53 .../modules/sharedaddy/images/smart-pocket.png | Bin 0 -> 1494 bytes
54 .../modules/sharedaddy/images/smart-pocket@××.png | Bin 0 -> 2125 bytes
55 plugins/jetpack/modules/shortcodes/bandcamp.php | 142 +
56 plugins/jetpack/modules/social-links.php | 10 +
57 .../jetpack/modules/social-links/social-links.php | 169 +
58 .../jetpack/modules/widgets/twitter-timeline.php | 214 ++
59 48 files changed, 7643 insertions(+)
60
61 diff --git a/plugins/jetpack/_inc/genericons.css b/plugins/jetpack/_inc/genericons.css
62 new file mode 100644
63 index 0000000..599002c
64 --- /dev/null
65 +++ b/plugins/jetpack/_inc/genericons.css
66 @@ -0,0 +1,149 @@
67 +/* =Webfont, thanks to FontSquirrel.com for conversion!
68 +-------------------------------------------------------------- */
69 +@font-face {
70 + font-family: 'Genericons';
71 + src: url('../modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.eot');
72 + src: url('../modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.eot?#iefix') format('embedded-opentype'),
73 + url('../modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.woff') format('woff'),
74 + url('../modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.ttf') format('truetype'),
75 + url('../modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.svg#genericonsregular') format('svg');
76 + font-weight: normal;
77 + font-style: normal;
78 +}
79 +
80 +/**
81 + * All Genericons
82 + */
83 +
84 +.genericon {
85 + display: inline-block;
86 + width: 16px;
87 + height: 16px;
88 + -webkit-font-smoothing: antialiased;
89 + font-size: 16px;
90 + line-height: 1;
91 + font-family: 'Genericons';
92 + text-decoration: inherit;
93 + font-weight: normal;
94 + font-style: normal;
95 + vertical-align: top;
96 +}
97 +
98 +/**
99 + * IE7 and IE6 hacks
100 + */
101 +
102 +.genericon {
103 + *overflow: auto;
104 + *zoom: 1;
105 + *display: inline;
106 +}
107 +
108 +/**
109 + * Individual icons
110 + */
111 +
112 +/* Post formats */
113 +.genericon-standard:before { content: '\f100'; }
114 +.genericon-aside:before { content: '\f101'; }
115 +.genericon-image:before { content: '\f102'; }
116 +.genericon-gallery:before { content: '\f103'; }
117 +.genericon-video:before { content: '\f104'; }
118 +.genericon-status:before { content: '\f105'; }
119 +.genericon-quote:before { content: '\f106'; }
120 +.genericon-link:before { content: '\f107'; }
121 +.genericon-chat:before { content: '\f108'; }
122 +.genericon-audio:before { content: '\f109'; }
123 +
124 +/* Social icons */
125 +.genericon-github:before { content: '\f200'; }
126 +.genericon-dribbble:before { content: '\f201'; }
127 +.genericon-twitter:before { content: '\f202'; }
128 +.genericon-facebook:before { content: '\f203'; }
129 +.genericon-facebook-alt:before { content: '\f204'; }
130 +.genericon-wordpress:before { content: '\f205'; }
131 +.genericon-googleplus:before { content: '\f206'; }
132 +.genericon-linkedin:before { content: '\f207'; }
133 +.genericon-linkedin-alt:before { content: '\f208'; }
134 +.genericon-pinterest:before { content: '\f209'; }
135 +.genericon-pinterest-alt:before { content: '\f210'; }
136 +.genericon-flickr:before { content: '\f211'; }
137 +.genericon-vimeo:before { content: '\f212'; }
138 +.genericon-youtube:before { content: '\f213'; }
139 +.genericon-tumblr:before { content: '\f214'; }
140 +.genericon-instagram:before { content: '\f215'; }
141 +.genericon-codepen:before { content: '\f216'; }
142 +
143 +/* Meta icons */
144 +.genericon-comment:before { content: '\f300'; }
145 +.genericon-category:before { content: '\f301'; }
146 +.genericon-tag:before { content: '\f302'; }
147 +.genericon-time:before { content: '\f303'; }
148 +.genericon-user:before { content: '\f304'; }
149 +.genericon-day:before { content: '\f305'; }
150 +.genericon-week:before { content: '\f306'; }
151 +.genericon-month:before { content: '\f307'; }
152 +.genericon-pinned:before { content: '\f308'; }
153 +
154 +/* Other icons */
155 +.genericon-search:before { content: '\f400'; }
156 +.genericon-unzoom:before { content: '\f401'; }
157 +.genericon-zoom:before { content: '\f402'; }
158 +.genericon-show:before { content: '\f403'; }
159 +.genericon-hide:before { content: '\f404'; }
160 +.genericon-close:before { content: '\f405'; }
161 +.genericon-close-alt:before { content: '\f406'; }
162 +.genericon-trash:before { content: '\f407'; }
163 +.genericon-star:before { content: '\f408'; }
164 +.genericon-home:before { content: '\f409'; }
165 +.genericon-mail:before { content: '\f410'; }
166 +.genericon-edit:before { content: '\f411'; }
167 +.genericon-reply:before { content: '\f412'; }
168 +.genericon-feed:before { content: '\f413'; }
169 +.genericon-warning:before { content: '\f414'; }
170 +.genericon-share:before { content: '\f415'; }
171 +.genericon-attachment:before { content: '\f416'; }
172 +.genericon-location:before { content: '\f417'; }
173 +.genericon-checkmark:before { content: '\f418'; }
174 +.genericon-menu:before { content: '\f419'; }
175 +.genericon-top:before { content: '\f420'; }
176 +.genericon-minimize:before { content: '\f421'; }
177 +.genericon-maximize:before { content: '\f422'; }
178 +.genericon-404:before { content: '\f423'; }
179 +.genericon-spam:before { content: '\f424'; }
180 +.genericon-summary:before { content: '\f425'; }
181 +.genericon-cloud:before { content: '\f426'; }
182 +.genericon-key:before { content: '\f427'; }
183 +.genericon-dot:before { content: '\f428'; }
184 +.genericon-next:before { content: '\f429'; }
185 +.genericon-previous:before { content: '\f430'; }
186 +.genericon-expand:before { content: '\f431'; }
187 +.genericon-collapse:before { content: '\f432'; }
188 +.genericon-dropdown:before { content: '\f433'; }
189 +.genericon-dropdown-left:before { content: '\f434'; }
190 +.genericon-top:before { content: '\f435'; }
191 +.genericon-draggable:before { content: '\f436'; }
192 +.genericon-phone:before { content: '\f437'; }
193 +.genericon-send-to-phone:before { content: '\f438'; }
194 +.genericon-plugin:before { content: '\f439'; }
195 +.genericon-cloud-download:before { content: '\f440'; }
196 +.genericon-cloud-upload:before { content: '\f441'; }
197 +.genericon-external:before { content: '\f442'; }
198 +.genericon-document:before { content: '\f443'; }
199 +.genericon-book:before { content: '\f444'; }
200 +.genericon-cog:before { content: '\f445'; }
201 +.genericon-unapprove:before { content: '\f446'; }
202 +.genericon-cart:before { content: '\f447'; }
203 +.genericon-pause:before { content: '\f448'; }
204 +.genericon-stop:before { content: '\f449'; }
205 +.genericon-skip-back:before { content: '\f450'; }
206 +.genericon-skip-ahead:before { content: '\f451'; }
207 +.genericon-play:before { content: '\f452'; }
208 +.genericon-tablet:before { content: '\f453'; }
209 +.genericon-send-to-tablet:before { content: '\f454'; }
210 +
211 +/* Generic shapes */
212 +.genericon-uparrow:before { content: '\f500'; }
213 +.genericon-rightarrow:before { content: '\f501'; }
214 +.genericon-downarrow:before { content: '\f502'; }
215 +.genericon-leftarrow:before { content: '\f503'; }
216
217 diff --git a/plugins/jetpack/class.jetpack-bbpress-json-api-compat.php b/plugins/jetpack/class.jetpack-bbpress-json-api-compat.php
218 new file mode 100644
219 index 0000000..3c7935d
220 --- /dev/null
221 +++ b/plugins/jetpack/class.jetpack-bbpress-json-api-compat.php
222 @@ -0,0 +1,108 @@
223 +<?php
224 +/**
225 +* bbPress & Jetpack REST API Compatibility
226 +* Enables bbPress to work with the Jetpack REST API
227 +*/
228 +class bbPress_Jetpack_REST_API {
229 +
230 + private static $instance;
231 +
232 + public static function instance() {
233 + if ( isset( self::$instance ) )
234 + return self::$instance;
235 +
236 + self::$instance = new self;
237 + }
238 +
239 + private function __construct() {
240 + add_filter( 'rest_api_allowed_post_types', array( $this, 'allow_bbpress_post_types' ) );
241 + add_filter( 'bbp_map_meta_caps', array( $this, 'adjust_meta_caps' ), 10, 4 );
242 + add_filter( 'rest_api_allowed_public_metadata', array( $this, 'allow_bbpress_public_metadata' ) );
243 + }
244 +
245 + function allow_bbpress_post_types( $allowed_post_types ) {
246 +
247 + // only run for REST API requests
248 + if ( ! defined( 'REST_API_REQUEST' ) || ! REST_API_REQUEST )
249 + return $allowed_post_types;
250 +
251 + $allowed_post_types[] = 'forum';
252 + $allowed_post_types[] = 'topic';
253 + $allowed_post_types[] = 'reply';
254 + return $allowed_post_types;
255 + }
256 +
257 + function allow_bbpress_public_metadata( $allowed_meta_keys ) {
258 +
259 + // only run for REST API requests
260 + if ( ! defined( 'REST_API_REQUEST' ) || ! REST_API_REQUEST )
261 + return $allowed_meta_keys;
262 +
263 + $allowed_meta_keys[] = '_bbp_forum_id';
264 + $allowed_meta_keys[] = '_bbp_topic_id';
265 + $allowed_meta_keys[] = '_bbp_status';
266 + $allowed_meta_keys[] = '_bbp_forum_type';
267 + $allowed_meta_keys[] = '_bbp_forum_subforum_count';
268 + $allowed_meta_keys[] = '_bbp_reply_count';
269 + $allowed_meta_keys[] = '_bbp_total_reply_count';
270 + $allowed_meta_keys[] = '_bbp_topic_count';
271 + $allowed_meta_keys[] = '_bbp_total_topic_count';
272 + $allowed_meta_keys[] = '_bbp_topic_count_hidden';
273 + $allowed_meta_keys[] = '_bbp_last_topic_id';
274 + $allowed_meta_keys[] = '_bbp_last_reply_id';
275 + $allowed_meta_keys[] = '_bbp_last_active_time';
276 + $allowed_meta_keys[] = '_bbp_last_active_id';
277 + $allowed_meta_keys[] = '_bbp_sticky_topics';
278 + $allowed_meta_keys[] = '_bbp_voice_count';
279 + $allowed_meta_keys[] = '_bbp_reply_count_hidden';
280 + $allowed_meta_keys[] = '_bbp_anonymous_reply_count';
281 +
282 + return $allowed_meta_keys;
283 + }
284 +
285 + function adjust_meta_caps( $caps, $cap, $user_id, $args ) {
286 +
287 + // only run for REST API requests
288 + if ( ! defined( 'REST_API_REQUEST' ) || ! REST_API_REQUEST )
289 + return $caps;
290 +
291 + // only modify caps for meta caps and for bbPress meta keys
292 + if ( ! in_array( $cap, array( 'edit_post_meta', 'delete_post_meta', 'add_post_meta' ) ) || empty( $args[1] ) || false === strpos( $args[1], '_bbp_' ) )
293 + return $caps;
294 +
295 + // $args[0] could be a post ID or a post_type string
296 + if ( is_int( $args[0] ) ) {
297 + $_post = get_post( $args[0] );
298 + if ( ! empty( $_post ) ) {
299 + $post_type = get_post_type_object( $_post->post_type );
300 + }
301 + } elseif ( is_string( $args[0] ) ) {
302 + $post_type = get_post_type_object( $args[0] );
303 + }
304 +
305 + // no post type found, bail
306 + if ( empty( $post_type ) )
307 + return $caps;
308 +
309 + // reset the needed caps
310 + $caps = array();
311 +
312 + // Add 'do_not_allow' cap if user is spam or deleted
313 + if ( bbp_is_user_inactive( $user_id ) ) {
314 + $caps[] = 'do_not_allow';
315 +
316 + // Moderators can always edit meta
317 + } elseif ( user_can( $user_id, 'moderate' ) ) {
318 + $caps[] = 'moderate';
319 +
320 + // Unknown so map to edit_posts
321 + } else {
322 + $caps[] = $post_type->cap->edit_posts;
323 + }
324 +
325 + return $caps;
326 + }
327 +
328 +}
329 +
330 +bbPress_Jetpack_REST_API::instance();
331
332 diff --git a/plugins/jetpack/class.jetpack-client-server.php b/plugins/jetpack/class.jetpack-client-server.php
333 new file mode 100644
334 index 0000000..1c0fe25
335 --- /dev/null
336 +++ b/plugins/jetpack/class.jetpack-client-server.php
337 @@ -0,0 +1,219 @@
338 +<?php
339 +
340 +/**
341 + * Client = Plugin
342 + * Client Server = API Methods the Plugin must respond to
343 + *
344 + * @todo Roll this into Jetpack? There's only one 'public' method now: ::authorize().
345 + */
346 +class Jetpack_Client_Server {
347 + function authorize() {
348 + $data = stripslashes_deep( $_GET );
349 +
350 + $args = array();
351 +
352 + $redirect = isset( $data['redirect'] ) ? esc_url_raw( (string) $data['redirect'] ) : '';
353 +
354 + do {
355 + $jetpack = Jetpack::init();
356 + $role = $jetpack->translate_current_user_to_role();
357 + if ( !$role ) {
358 + Jetpack::state( 'error', 'no_role' );
359 + break;
360 + }
361 +
362 + $cap = $jetpack->translate_role_to_cap( $role );
363 + if ( !$cap ) {
364 + Jetpack::state( 'error', 'no_cap' );
365 + break;
366 + }
367 +
368 + check_admin_referer( "jetpack-authorize_{$role}_{$redirect}" );
369 +
370 + if ( !empty( $data['error'] ) ) {
371 + Jetpack::state( 'error', $data['error'] );
372 + break;
373 + }
374 +
375 + if ( empty( $data['state'] ) ) {
376 + Jetpack::state( 'error', 'no_state' );
377 + break;
378 + }
379 +
380 + if ( !ctype_digit( $data['state'] ) ) {
381 + Jetpack::state( 'error', 'invalid_state' );
382 + break;
383 + }
384 +
385 + $current_user_id = get_current_user_id();
386 + if ( $current_user_id != $data['state'] ) {
387 + Jetpack::state( 'error', 'wrong_state' );
388 + break;
389 + }
390 +
391 + if ( empty( $data['code'] ) ) {
392 + Jetpack::state( 'error', 'no_code' );
393 + break;
394 + }
395 +
396 + $token = $this->get_token( $data );
397 +
398 + if ( is_wp_error( $token ) ) {
399 + if ( $error = $token->get_error_code() )
400 + Jetpack::state( 'error', $error );
401 + else
402 + Jetpack::state( 'error', 'invalid_token' );
403 +
404 + Jetpack::state( 'error_description', $token->get_error_message() );
405 +
406 + break;
407 + }
408 +
409 + if ( !$token ) {
410 + Jetpack::state( 'error', 'no_token' );
411 + break;
412 + }
413 +
414 + $is_master_user = ! Jetpack::is_active();
415 +
416 + Jetpack::update_user_token( $current_user_id, sprintf( '%s.%d', $token, $current_user_id ), $is_master_user );
417 +
418 +
419 + if ( $is_master_user ) {
420 + Jetpack::state( 'message', 'authorized' );
421 + } else {
422 + Jetpack::state( 'message', 'linked' );
423 + // Don't activate anything since we are just connecting a user.
424 + break;
425 + }
426 +
427 + if ( $active_modules = Jetpack::get_option( 'active_modules' ) ) {
428 + Jetpack::delete_option( 'active_modules' );
429 +
430 + Jetpack::activate_default_modules( 999, 1, $active_modules );
431 + } else {
432 + Jetpack::activate_default_modules();
433 + }
434 +
435 + $jetpack->sync->register( 'noop' ); // Spawn a sync to make sure the Jetpack Servers know what modules are active.
436 +
437 + // Start nonce cleaner
438 + wp_clear_scheduled_hook( 'jetpack_clean_nonces' );
439 + wp_schedule_event( time(), 'hourly', 'jetpack_clean_nonces' );
440 + } while ( false );
441 +
442 + if ( wp_validate_redirect( $redirect ) ) {
443 + wp_safe_redirect( $redirect );
444 + } else {
445 + wp_safe_redirect( Jetpack::admin_url() );
446 + }
447 +
448 + exit;
449 + }
450 +
451 + public static function deactivate_plugin( $probable_file, $probable_title ) {
452 + if ( is_plugin_active( $probable_file ) ) {
453 + deactivate_plugins( $probable_file );
454 + return 1;
455 + } else {
456 + // If the plugin is not in the usual place, try looking through all active plugins.
457 + $active_plugins = get_option( 'active_plugins', array() );
458 + foreach ( $active_plugins as $plugin ) {
459 + $data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
460 + if ( $data['Name'] == $probable_title ) {
461 + deactivate_plugins( $plugin );
462 + return 1;
463 + }
464 + }
465 + }
466 +
467 + return 0;
468 + }
469 +
470 + /**
471 + * @return object|WP_Error
472 + */
473 + function get_token( $data ) {
474 + $jetpack = Jetpack::init();
475 + $role = $jetpack->translate_current_user_to_role();
476 +
477 + if ( !$role ) {
478 + return new Jetpack_Error( 'role', __( 'An administrator for this blog must set up the Jetpack connection.', 'jetpack' ) );
479 + }
480 +
481 + $client_secret = Jetpack_Data::get_access_token();
482 + if ( !$client_secret ) {
483 + return new Jetpack_Error( 'client_secret', __( 'You need to register your Jetpack before connecting it.', 'jetpack' ) );
484 + }
485 +
486 + $redirect = isset( $data['redirect'] ) ? esc_url_raw( (string) $data['redirect'] ) : '';
487 +
488 + $body = array(
489 + 'client_id' => Jetpack::get_option( 'id' ),
490 + 'client_secret' => $client_secret->secret,
491 + 'grant_type' => 'authorization_code',
492 + 'code' => $data['code'],
493 + 'redirect_uri' => add_query_arg( array(
494 + 'action' => 'authorize',
495 + '_wpnonce' => wp_create_nonce( "jetpack-authorize_{$role}_{$redirect}" ),
496 + 'redirect' => $redirect ? urlencode( $redirect ) : false,
497 + ), menu_page_url( 'jetpack', false ) ),
498 + );
499 +
500 + $args = array(
501 + 'method' => 'POST',
502 + 'body' => $body,
503 + 'headers' => array(
504 + 'Accept' => 'application/json',
505 + ),
506 + );
507 + $response = Jetpack_Client::_wp_remote_request( Jetpack::fix_url_for_bad_hosts( Jetpack::api_url( 'token' ), $args ), $args );
508 +
509 + if ( is_wp_error( $response ) ) {
510 + return new Jetpack_Error( 'token_http_request_failed', $response->get_error_message() );
511 + }
512 +
513 + $code = wp_remote_retrieve_response_code( $response );
514 + $entity = wp_remote_retrieve_body( $response );
515 +
516 + if ( $entity )
517 + $json = json_decode( $entity );
518 + else
519 + $json = false;
520 +
521 + if ( 200 != $code || !empty( $json->error ) ) {
522 + if ( empty( $json->error ) )
523 + return new Jetpack_Error( 'unknown', '', $code );
524 +
525 + $error_description = isset( $json->error_description ) ? sprintf( __( 'Error Details: %s', 'jetpack' ), (string) $json->error_description ) : '';
526 +
527 + return new Jetpack_Error( (string) $json->error, $error_description, $code );
528 + }
529 +
530 + if ( empty( $json->access_token ) || !is_scalar( $json->access_token ) ) {
531 + return new Jetpack_Error( 'access_token', '', $code );
532 + }
533 +
534 + if ( empty( $json->token_type ) || 'X_JETPACK' != strtoupper( $json->token_type ) ) {
535 + return new Jetpack_Error( 'token_type', '', $code );
536 + }
537 +
538 + if ( empty( $json->scope ) ) {
539 + return new Jetpack_Error( 'scope', 'No Scope', $code );
540 + }
541 + @list( $role, $hmac ) = explode( ':', $json->scope );
542 + if ( empty( $role ) || empty( $hmac ) ) {
543 + return new Jetpack_Error( 'scope', 'Malformed Scope', $code );
544 + }
545 + if ( $jetpack->sign_role( $role ) !== $json->scope ) {
546 + return new Jetpack_Error( 'scope', 'Invalid Scope', $code );
547 + }
548 +
549 + if ( !$cap = $jetpack->translate_role_to_cap( $role ) )
550 + return new Jetpack_Error( 'scope', 'No Cap', $code );
551 + if ( !current_user_can( $cap ) )
552 + return new Jetpack_Error( 'scope', 'current_user_cannot', $code );
553 +
554 + return (string) $json->access_token;
555 + }
556 +}
557
558 diff --git a/plugins/jetpack/class.jetpack-client.php b/plugins/jetpack/class.jetpack-client.php
559 new file mode 100644
560 index 0000000..c414e08
561 --- /dev/null
562 +++ b/plugins/jetpack/class.jetpack-client.php
563 @@ -0,0 +1,215 @@
564 +<?php
565 +
566 +class Jetpack_Client {
567 + /**
568 + * Makes an authorized remote request using Jetpack_Signature
569 + *
570 + * @return array|WP_Error WP HTTP response on success
571 + */
572 + public static function remote_request( $args, $body = null ) {
573 + $defaults = array(
574 + 'url' => '',
575 + 'user_id' => 0,
576 + 'blog_id' => 0,
577 + 'auth_location' => JETPACK_CLIENT__AUTH_LOCATION,
578 + 'method' => 'POST',
579 + 'timeout' => 10,
580 + 'redirection' => 0,
581 + );
582 +
583 + $args = wp_parse_args( $args, $defaults );
584 +
585 + $args['blog_id'] = (int) $args['blog_id'];
586 +
587 + if ( 'header' != $args['auth_location'] ) {
588 + $args['auth_location'] = 'query_string';
589 + }
590 +
591 + $token = Jetpack_Data::get_access_token( $args['user_id'] );
592 + if ( !$token ) {
593 + return new Jetpack_Error( 'missing_token' );
594 + }
595 +
596 + $method = strtoupper( $args['method'] );
597 +
598 + $timeout = intval( $args['timeout'] );
599 +
600 + $redirection = $args['redirection'];
601 +
602 + $request = compact( 'method', 'body', 'timeout', 'redirection' );
603 +
604 + @list( $token_key, $secret ) = explode( '.', $token->secret );
605 + if ( empty( $token ) || empty( $secret ) ) {
606 + return new Jetpack_Error( 'malformed_token' );
607 + }
608 +
609 + $token_key = sprintf( '%s:%d:%d', $token_key, JETPACK__API_VERSION, $token->external_user_id );
610 +
611 + require_once dirname( __FILE__ ) . '/class.jetpack-signature.php';
612 +
613 + $time_diff = (int) Jetpack::get_option( 'time_diff' );
614 + $jetpack_signature = new Jetpack_Signature( $token->secret, $time_diff );
615 +
616 + $timestamp = time() + $time_diff;
617 + $nonce = wp_generate_password( 10, false );
618 +
619 + // Kind of annoying. Maybe refactor Jetpack_Signature to handle body-hashing
620 + if ( is_null( $body ) ) {
621 + $body_hash = '';
622 + } else {
623 + if ( !is_string( $body ) ) {
624 + return new Jetpack_Error( 'invalid_body', 'Body is malformed.' );
625 + }
626 + $body_hash = jetpack_sha1_base64( $body );
627 + }
628 +
629 + $auth = array(
630 + 'token' => $token_key,
631 + 'timestamp' => $timestamp,
632 + 'nonce' => $nonce,
633 + 'body-hash' => $body_hash,
634 + );
635 +
636 + if ( false !== strpos( $args['url'], 'xmlrpc.php' ) ) {
637 + $url_args = array(
638 + 'for' => 'jetpack',
639 + 'blog_id' => $args['blog_id'],
640 + );
641 + } else {
642 + $url_args = array();
643 + }
644 +
645 + if ( 'header' != $args['auth_location'] ) {
646 + $url_args += $auth;
647 + }
648 +
649 + $url = add_query_arg( urlencode_deep( $url_args ), $args['url'] );
650 + $url = Jetpack::fix_url_for_bad_hosts( $url, $request );
651 +
652 + $signature = $jetpack_signature->sign_request( $token_key, $timestamp, $nonce, $body_hash, $method, $url, $body, false );
653 +
654 + if ( !$signature || is_wp_error( $signature ) ) {
655 + return $signature;
656 + }
657 +
658 + // Send an Authorization header so various caches/proxies do the right thing
659 + $auth['signature'] = $signature;
660 + $auth['version'] = JETPACK__VERSION;
661 + $header_pieces = array();
662 + foreach ( $auth as $key => $value ) {
663 + $header_pieces[] = sprintf( '%s="%s"', $key, $value );
664 + }
665 + $request['headers'] = array(
666 + 'Authorization' => "X_JETPACK " . join( ' ', $header_pieces ),
667 + );
668 +
669 + if ( 'header' != $args['auth_location'] ) {
670 + $url = add_query_arg( 'signature', urlencode( $signature ), $url );
671 + }
672 +
673 + return Jetpack_Client::_wp_remote_request( $url, $request );
674 + }
675 +
676 + /**
677 + * Wrapper for wp_remote_request(). Turns off SSL verification for certain SSL errors.
678 + * This is lame, but many, many, many hosts have misconfigured SSL.
679 + *
680 + * When Jetpack is registered, the jetpack_fallback_no_verify_ssl_certs option is set to the current time if:
681 + * 1. a certificate error is found AND
682 + * 2. not verifying the certificate works around the problem.
683 + *
684 + * The option is checked on each request.
685 + *
686 + * @internal
687 + * @todo: Better fallbacks (bundled certs?), feedback, UI, ....
688 + * @see Jetpack::fix_url_for_bad_hosts()
689 + *
690 + * @return array|WP_Error WP HTTP response on success
691 + */
692 + public static function _wp_remote_request( $url, $args, $set_fallback = false ) {
693 + $fallback = Jetpack::get_option( 'fallback_no_verify_ssl_certs' );
694 + if ( false === $fallback ) {
695 + Jetpack::update_option( 'fallback_no_verify_ssl_certs', 0 );
696 + }
697 +
698 + if ( (int) $fallback ) {
699 + // We're flagged to fallback
700 + $args['sslverify'] = false;
701 + }
702 +
703 + $response = wp_remote_request( $url, $args );
704 +
705 + if (
706 + !$set_fallback // We're not allowed to set the flag on this request, so whatever happens happens
707 + ||
708 + isset( $args['sslverify'] ) && !$args['sslverify'] // No verification - no point in doing it again
709 + ||
710 + !is_wp_error( $response ) // Let it ride
711 + ) {
712 + Jetpack_Client::set_time_diff( $response, $set_fallback );
713 + return $response;
714 + }
715 +
716 + // At this point, we're not flagged to fallback and we are allowed to set the flag on this request.
717 +
718 + $message = $response->get_error_message();
719 +
720 + // Is it an SSL Certificate verification error?
721 + if (
722 + false === strpos( $message, '14090086' ) // OpenSSL SSL3 certificate error
723 + &&
724 + false === strpos( $message, '1407E086' ) // OpenSSL SSL2 certificate error
725 + &&
726 + false === strpos( $message, 'error setting certificate verify locations' ) // cURL CA bundle not found
727 + &&
728 + false === strpos( $message, 'Peer certificate cannot be authenticated with' ) // cURL CURLE_SSL_CACERT: CA bundle found, but not helpful
729 + // different versions of curl have different error messages
730 + // this string should catch them all
731 + &&
732 + false === strpos( $message, 'Problem with the SSL CA cert' ) // cURL CURLE_SSL_CACERT_BADFILE: probably access rights
733 + ) {
734 + // No, it is not.
735 + return $response;
736 + }
737 +
738 + // Redo the request without SSL certificate verification.
739 + $args['sslverify'] = false;
740 + $response = wp_remote_request( $url, $args );
741 +
742 + if ( !is_wp_error( $response ) ) {
743 + // The request went through this time, flag for future fallbacks
744 + Jetpack::update_option( 'fallback_no_verify_ssl_certs', time() );
745 + Jetpack_Client::set_time_diff( $response, $set_fallback );
746 + }
747 +
748 + return $response;
749 + }
750 +
751 + public static function set_time_diff( &$response, $force_set = false ) {
752 + $code = wp_remote_retrieve_response_code( $response );
753 +
754 + // Only trust the Date header on some responses
755 + if ( 200 != $code && 304 != $code && 400 != $code && 401 != $code ) {
756 + return;
757 + }
758 +
759 + if ( !$date = wp_remote_retrieve_header( $response, 'date' ) ) {
760 + return;
761 + }
762 +
763 + if ( 0 >= $time = (int) strtotime( $date ) ) {
764 + return;
765 + }
766 +
767 + $time_diff = $time - time();
768 +
769 + if ( $force_set ) { // during register
770 + Jetpack::update_option( 'time_diff', $time_diff );
771 + } else { // otherwise
772 + $old_diff = Jetpack::get_option( 'time_diff' );
773 + if ( false === $old_diff || abs( $time_diff - (int) $old_diff ) > 10 ) {
774 + Jetpack::update_option( 'time_diff', $time_diff );
775 + }
776 + }
777 + }
778 +}
779
780 diff --git a/plugins/jetpack/class.jetpack-data.php b/plugins/jetpack/class.jetpack-data.php
781 new file mode 100644
782 index 0000000..b43e6a4
783 --- /dev/null
784 +++ b/plugins/jetpack/class.jetpack-data.php
785 @@ -0,0 +1,42 @@
786 +<?php
787 +
788 +class Jetpack_Data {
789 + /**
790 + * Gets locally stored token
791 + *
792 + * @return object|false
793 + */
794 + public static function get_access_token( $user_id = false ) {
795 + if ( $user_id ) {
796 + if ( !$tokens = Jetpack::get_option( 'user_tokens' ) ) {
797 + return false;
798 + }
799 + if ( $user_id === JETPACK_MASTER_USER ) {
800 + if ( !$user_id = Jetpack::get_option( 'master_user' ) ) {
801 + return false;
802 + }
803 + }
804 + if ( !isset( $tokens[$user_id] ) || !$token = $tokens[$user_id] ) {
805 + return false;
806 + }
807 + $token_chunks = explode( '.', $token );
808 + if ( empty( $token_chunks[1] ) || empty( $token_chunks[2] ) ) {
809 + return false;
810 + }
811 + if ( $user_id != $token_chunks[2] ) {
812 + return false;
813 + }
814 + $token = "{$token_chunks[0]}.{$token_chunks[1]}";
815 + } else {
816 + $token = Jetpack::get_option( 'blog_token' );
817 + if ( empty( $token ) ) {
818 + return false;
819 + }
820 + }
821 +
822 + return (object) array(
823 + 'secret' => $token,
824 + 'external_user_id' => (int) $user_id,
825 + );
826 + }
827 +}
828
829 diff --git a/plugins/jetpack/class.jetpack-debugger.php b/plugins/jetpack/class.jetpack-debugger.php
830 new file mode 100644
831 index 0000000..01c71e2
832 --- /dev/null
833 +++ b/plugins/jetpack/class.jetpack-debugger.php
834 @@ -0,0 +1,353 @@
835 +<?php
836 +
837 +function is_jetpack_support_open() {
838 + try {
839 + $response = wp_remote_request( "http://jetpack.me/is-support-open" );
840 + $body = wp_remote_retrieve_body( $response );
841 + $json = json_decode( $body );
842 + return ( ( bool )$json->is_support_open );
843 + }
844 + catch ( Exception $e ) {
845 + return true;
846 + }
847 +}
848 +
849 +function jetpack_increase_timeout($time) {
850 + $time = 20; //seconds
851 + return $time;
852 +}
853 +
854 +
855 +function jetpack_debug_display_handler() {
856 + if ( ! current_user_can( 'manage_options' ) )
857 + wp_die( esc_html__('You do not have sufficient permissions to access this page.', 'jetpack' ) );
858 +
859 + global $current_user;
860 + get_currentuserinfo();
861 +
862 + $user_id = get_current_user_id();
863 + $user_tokens = Jetpack::get_option( 'user_tokens' );
864 + if ( is_array( $user_tokens ) && array_key_exists( $user_id, $user_tokens ) ) {
865 + $user_token = $user_tokens[$user_id];
866 + } else {
867 + $user_token = '[this user has no token]';
868 + }
869 + unset( $user_tokens );
870 +
871 + $debug_info = "\r\n";
872 + foreach ( array(
873 + 'CLIENT_ID' => 'id',
874 + 'BLOG_TOKEN' => 'blog_token',
875 + 'MASTER_USER' => 'master_user',
876 + 'CERT' => 'fallback_no_verify_ssl_certs',
877 + 'TIME_DIFF' => 'time_diff',
878 + 'VERSION' => 'version',
879 + 'OLD_VERSION' => 'old_version',
880 + 'PUBLIC' => 'public',
881 + ) as $label => $option_name ) {
882 + $debug_info .= "\r\n" . esc_html( $label . ": " . Jetpack::get_option( $option_name ) );
883 + }
884 +
885 + $debug_info .= "\r\n" . esc_html( "USER_ID: " . $user_id );
886 + $debug_info .= "\r\n" . esc_html( "USER_TOKEN: " . $user_token );
887 + $debug_info .= "\r\n" . esc_html( "PHP_VERSION: " . PHP_VERSION );
888 + $debug_info .= "\r\n" . esc_html( "WORDPRESS_VERSION: " . $GLOBALS['wp_version'] );
889 + $debug_info .= "\r\n" . esc_html( "JETPACK__VERSION: " . JETPACK__VERSION );
890 + $debug_info .= "\r\n" . esc_html( "JETPACK__PLUGIN_DIR: " . JETPACK__PLUGIN_DIR );
891 + $debug_info .= "\r\n" . esc_html( "SITE_URL: " . site_url() );
892 + $debug_info .= "\r\n" . esc_html( "HOME_URL: " . home_url() );
893 +
894 + $debug_info .= "\r\n\r\nTEST RESULTS:\r\n\r\n";
895 + $debug_raw_info = '';
896 +
897 +
898 + $tests = array();
899 +
900 + $tests['HTTP']['result'] = wp_remote_get( preg_replace( '/^https:/', 'http:', JETPACK__API_BASE ) . 'test/1/' );
901 + $tests['HTTP']['fail_message'] = esc_html__( 'Your site isn’t reaching the Jetpack servers.', 'jetpack' );
902 +
903 + $tests['HTTPS']['result'] = wp_remote_get( preg_replace( '/^http:/', 'https:', JETPACK__API_BASE ) . 'test/1/' );
904 + $tests['HTTPS']['fail_message'] = esc_html__( 'Your site isn’t securely reaching the Jetpack servers.', 'jetpack' );
905 +
906 +
907 + $self_xml_rpc_url = site_url( 'xmlrpc.php' );
908 +
909 + $args = array();
910 + $testsite_url = Jetpack::fix_url_for_bad_hosts( JETPACK__API_BASE . 'testsite/1/?url=', $args );
911 +
912 + add_filter( 'http_request_timeout', 'jetpack_increase_timeout' );
913 +
914 + $tests['SELF']['result'] = wp_remote_get( $testsite_url . $self_xml_rpc_url );
915 + $tests['SELF']['fail_message'] = esc_html__( 'It looks like your site can not communicate properly with Jetpack.', 'jetpack' );
916 +
917 + remove_filter( 'http_request_timeout', 'jetpack_increase_timeout' );
918 +
919 + ?>
920 + <div class="wrap">
921 + <h2><?php esc_html_e( 'Jetpack Debugging Center', 'jetpack' ); ?></h2>
922 + <h3><?php _e( "Testing your site's compatibily with Jetpack...", 'jetpack' ); ?></h3>
923 + <div class="jetpack-debug-test-container">
924 + <?php
925 + ob_start();
926 + foreach ( $tests as $test_name => $test_info ) :
927 + if ( is_wp_error( $test_info['result'] ) ||
928 + false == ( $response_code = wp_remote_retrieve_response_code( $test_info['result'] ) ) ||
929 + '200' != $response_code ) {
930 + $debug_info .= $test_name . ": FAIL\r\n";
931 + ?>
932 + <div class="jetpack-test-error">
933 + <p>
934 + <a class="jetpack-test-heading" href="#"><?php echo $test_info['fail_message']; ?>
935 + <span class="noticon noticon-collapse"></span>
936 + </a>
937 + </p>
938 + <pre class="jetpack-test-details"><?php esc_html_e( $test_name , 'jetpack'); ?>:
939 +<?php esc_html_e( is_wp_error( $test_info['result'] ) ? $test_info['result']->get_error_message() : print_r( $test_info['result'], 1 ) ); ?></pre>
940 + </div><?php
941 + } else {
942 + $debug_info .= $test_name . ": PASS\r\n";
943 + }
944 + $debug_raw_info .= "\r\n\r\n" . $test_name . "\r\n" . esc_html( print_r( $test_info['result'], 1 ) );
945 + ?>
946 + <?php endforeach;
947 + $html = ob_get_clean();
948 +
949 + if ( '' == trim( $html ) ) {
950 + echo '<div class="jetpack-tests-succed">' . esc_html__( 'Your Jetpack setup looks a-okay!', 'jetpack' ) . '</div>';
951 + }
952 + else {
953 + echo '<h3>' . esc_html__( 'There seems to be a problem with your site’s ability to communicate with Jetpack!', 'jetpack' ) . '</h3>';
954 + echo $html;
955 + }
956 + $debug_info .= "\r\n\r\nRAW TEST RESULTS:" . $debug_raw_info ."\r\n";
957 + ?>
958 + </div>
959 + <div class="entry-content">
960 + <h3><?php esc_html_e( 'Trouble with Jetpack?', 'jetpack' ); ?></h3>
961 + <h4><?php esc_html_e( 'It may be caused by one of these issues, which you can diagnose yourself:', 'jetpack' ); ?></h4>
962 + <ol>
963 + <li><b><em><?php esc_html_e( 'A known issue.', 'jetpack' ); ?></em></b> <?php echo sprintf( __( 'Some themes and plugins have <a href="%1$s" target="_blank">known conflicts</a> with Jetpack – check the <a href="%2$s" target="_blank">list</a>. (You can also browse the <a href="%3$s">Jetpack support pages</a> or <a href="%4$s">Jetpack support forum</a> to see if others have experienced and solved the problem.)', 'jetpack' ), 'http://jetpack.me/known-issues/', 'http://jetpack.me/known-issues/', 'http://jetpack.me/support/', 'http://wordpress.org/support/plugin/jetpack' ); ?></li>
964 + <li><b><em><?php esc_html_e( 'An incompatible plugin.', 'jetpack' ); ?></em></b> <?php esc_html_e( "Find out by disabling all plugins except Jetpack. If the problem persists, it's not a plugin issue. If the problem is solved, turn your plugins on one by one until the problem pops up again – there's the culprit! Let us know, and we'll try to help.", 'jetpack' ); ?></li>
965 + <li><b><em><?php esc_html_e( 'A theme conflict.', 'jetpack' ); ?></em></b> <?php esc_html_e( "If your problem isn't known or caused by a plugin, try activating Twenty Twelve (the default WordPress theme). If this solves the problem, something in your theme is probably broken – let the theme's author know.", 'jetpack' ); ?></li>
966 + <li><b><em><?php esc_html_e( 'A problem with your XMLRPC file.', 'jetpack' ); ?></em></b> <?php echo sprintf( __( 'Load your <a href="%s">XMLRPC file</a>. It should say “XML-RPC server accepts POST requests only.” on a line by itself.', 'jetpack' ), site_url( 'xmlrpc.php' ) ); ?>
967 + <ul>
968 + <li>- <?php esc_html_e( "If it's not by itself, a theme or plugin is displaying extra characters. Try steps 2 and 3.", 'jetpack' ); ?></li>
969 + <li>- <?php esc_html_e( "If you get a 404 message, contact your web host. Their security may block XMLRPC.", 'jetpack' ); ?></li>
970 + </ul>
971 + </li>
972 + </ol>
973 + <p class="jetpack-show-contact-form"><?php _e( 'If none of these help you find a solution, <a href="#">click here to contact Jetpack support</a>. Tell us as much as you can about the issue and what steps you\'ve tried to resolve it, and one of our Happiness Engineers will be in touch to help.', 'jetpack' ); ?>
974 + </p>
975 + </div>
976 + <div id="contact-message" style="display:none">
977 + <?php if ( is_jetpack_support_open() ): ?>
978 + <form id="contactme" method="post" action="http://jetpack.me/contact-support/">
979 + <input type="hidden" name="action" value="submit">
980 + <input type="hidden" name="jetpack" value="needs-service">
981 +
982 + <input type="hidden" name="contact_form" id="contact_form" value="1">
983 + <input type="hidden" name="blog_url" id="blog_url" value="<?php echo esc_attr( site_url() ); ?>">
984 + <input type="hidden" name="subject" id="subject" value="from: <?php echo esc_attr( site_url() ); ?> Jetpack contact form">
985 + <div class="formbox">
986 + <label for="message" class="h"><?php esc_html_e( 'Please describe the problem you are having.', 'jetpack' ); ?></label>
987 + <textarea name="message" cols="40" rows="7" id="did"></textarea>
988 + </div>
989 +
990 + <div id="name_div" class="formbox">
991 + <label class="h" for="your_name"><?php esc_html_e( 'Name', 'jetpack' ); ?></label>
992 + <span class="errormsg"><?php esc_html_e( 'Let us know your name.', 'jetpack' ); ?></span>
993 + <input name="your_name" type="text" id="your_name" value="<?php esc_html_e( $current_user->display_name , 'jetpack'); ?>" size="40">
994 + </div>
995 +
996 + <div id="email_div" class="formbox">
997 + <label class="h" for="your_email"><?php esc_html_e( 'E-mail', 'jetpack' ); ?></label>
998 + <span class="errormsg"><?php esc_html_e( 'Use a valid email address.', 'jetpack' ); ?></span>
999 + <input name="your_email" type="text" id="your_email" value="<?php esc_html_e( $current_user->user_email , 'jetpack'); ?>" size="40">
1000 + </div>
1001 +
1002 + <div id="toggle_debug_info" class="formbox">
1003 + <p><?php _e( 'The test results and some other useful debug information will be sent to the support team. Please feel free to <a href="#">review/modify</a> this information.', 'jetpack' ); ?></p>
1004 + </div>
1005 +
1006 + <div id="debug_info_div" class="formbox" style="display:none">
1007 + <label class="h" for="debug_info"><?php esc_html_e( 'Debug Info', 'jetpack' ); ?></label>
1008 + <textarea name="debug_info" cols="40" rows="7" id="debug_info"><?php echo esc_attr( $debug_info ); ?></textarea>
1009 + </div>
1010 +
1011 + <div style="clear: both;"></div>
1012 +
1013 + <div id="blog_div" class="formbox">
1014 + <div id="submit_div" class="contact-support">
1015 + <input type="submit" name="submit" value="Contact Support">
1016 + </div>
1017 + </div>
1018 + <div style="clear: both;"></div>
1019 + </form>
1020 + <?php endif; ?>
1021 + </div>
1022 + </div>
1023 +<?php
1024 +}
1025 +
1026 +function jetpack_debug_admin_head() {
1027 + ?>
1028 + <style type="text/css">
1029 +
1030 + .jetpack-debug-test-container {
1031 + margin-top: 20px;
1032 + margin-bottom: 30px;
1033 + }
1034 +
1035 + .jetpack-tests-succed {
1036 + font-size: large;
1037 + color: #8BAB3E;
1038 + }
1039 +
1040 + .jetpack-test-details {
1041 + margin: 4px 6px;
1042 + padding: 10px;
1043 + overflow: auto;
1044 + display: none;
1045 + }
1046 +
1047 + .jetpack-test-error {
1048 + margin-bottom: 10px;
1049 + background: #FFEBE8;
1050 + border: solid 1px #C00;
1051 + border-radius: 3px;
1052 + }
1053 +
1054 + .jetpack-test-error p {
1055 + margin: 0;
1056 + padding: 0;
1057 + }
1058 +
1059 + .jetpack-test-error a.jetpack-test-heading {
1060 + padding: 4px 6px;
1061 + display: block;
1062 + text-decoration: none;
1063 + color: inherit;
1064 + }
1065 +
1066 + .jetpack-test-error .noticon {
1067 + float: right;
1068 + }
1069 +
1070 + form#contactme {
1071 + border: 1px solid #dfdfdf;
1072 + background: #eaf3fa;
1073 + padding: 20px;
1074 + margin: 10px;
1075 + background-color: #eaf3fa;
1076 + border-radius: 5px;
1077 + font-size: 15px;
1078 + font-family: "Open Sans", "Helvetica Neue", sans-serif;
1079 + }
1080 +
1081 + form#contactme label.h {
1082 + color: #444;
1083 + display: block;
1084 + font-weight: bold;
1085 + margin: 0 0 7px 10px;
1086 + text-shadow: 1px 1px 0 #fff;
1087 + }
1088 +
1089 + .formbox {
1090 + margin: 0 0 25px 0;
1091 + }
1092 +
1093 + .formbox input[type="text"], .formbox input[type="email"], .formbox input[type="url"], .formbox textarea {
1094 + border: 1px solid #e5e5e5;
1095 + border-radius: 11px;
1096 + box-shadow: inset 0 1px 1px rgba(0,0,0,0.1);
1097 + color: #666;
1098 + font-size: 14px;
1099 + padding: 10px;
1100 + width: 97%;
1101 + }
1102 + .formbox .contact-support input[type="submit"] {
1103 + float: right;
1104 + margin: 0 !important;
1105 + border-radius: 20px !important;
1106 + cursor: pointer;
1107 + font-size: 13pt !important;
1108 + height: auto !important;
1109 + margin: 0 0 2em 10px !important;
1110 + padding: 8px 16px !important;
1111 + background-color: #ddd;
1112 + border: 1px solid rgba(0,0,0,0.05);
1113 + border-top-color: rgba(255,255,255,0.1);
1114 + border-bottom-color: rgba(0,0,0,0.15);
1115 + color: #333;
1116 + font-weight: 400;
1117 + display: inline-block;
1118 + text-align: center;
1119 + text-decoration: none;
1120 + }
1121 +
1122 + .formbox span.errormsg {
1123 + margin: 0 0 10px 10px;
1124 + color: #d00;
1125 + display: none;
1126 + }
1127 +
1128 + .formbox.error span.errormsg {
1129 + display: block;
1130 + }
1131 +
1132 + #contact-message ul {
1133 + margin: 0 0 20px 10px;
1134 + }
1135 +
1136 + #contact-message li {
1137 + margin: 0 0 10px 10px;
1138 + list-style: disc;
1139 + display: list-item;
1140 + }
1141 +
1142 + </style>
1143 + <script type="text/javascript">
1144 + jQuery( document ).ready( function($) {
1145 +
1146 + $('#debug_info').prepend('jQuery version: ' + jQuery.fn.jquery + "\r\n");
1147 +
1148 + $( '.jetpack-test-error .jetpack-test-heading' ).on( 'click', function() {
1149 + $( this ).parents( '.jetpack-test-error' ).find( '.jetpack-test-details' ).slideToggle();
1150 + return false;
1151 + } );
1152 +
1153 + $( '.jetpack-show-contact-form a' ).on( 'click', function() {
1154 + $('#contact-message').slideToggle();
1155 + return false;
1156 + } );
1157 +
1158 + $( '#toggle_debug_info a' ).on( 'click', function() {
1159 + $('#debug_info_div').slideToggle();
1160 + return false;
1161 + } );
1162 +
1163 + $('form#contactme').on("submit", function(e){
1164 + var form = $(this);
1165 + var message = form.find('#did');
1166 + var name = form.find('#your_name');
1167 + var email = form.find('#your_email')
1168 + var validation_error = false;
1169 + if( !name.val() ) {
1170 + name.parents('.formbox').addClass('error');
1171 + validation_error = true;
1172 + }
1173 + if( !email.val() ) {
1174 + email.parents('.formbox').addClass('error');
1175 + validation_error = true;
1176 + }
1177 + if ( validation_error ) {
1178 + return false;
1179 + }
1180 + message.val(message.val() + "\r\n\r\n----------------------------------------------\r\n\r\nDEBUG INFO:\r\n" + $('#debug_info').val() );
1181 + return true;
1182 + });
1183 +
1184 + } );
1185 + </script>
1186 + <?php
1187 +}
1188
1189 diff --git a/plugins/jetpack/class.jetpack-error.php b/plugins/jetpack/class.jetpack-error.php
1190 new file mode 100644
1191 index 0000000..9b7725a
1192 --- /dev/null
1193 +++ b/plugins/jetpack/class.jetpack-error.php
1194 @@ -0,0 +1,3 @@
1195 +<?php
1196 +
1197 +class Jetpack_Error extends WP_Error {}
1198
1199 diff --git a/plugins/jetpack/class.jetpack-heartbeat.php b/plugins/jetpack/class.jetpack-heartbeat.php
1200 new file mode 100644
1201 index 0000000..40daf2a
1202 --- /dev/null
1203 +++ b/plugins/jetpack/class.jetpack-heartbeat.php
1204 @@ -0,0 +1,131 @@
1205 +<?php
1206 +
1207 +class Jetpack_Heartbeat {
1208 +
1209 + /**
1210 + * Jetpack object
1211 + *
1212 + * @since 2.3.3
1213 + * @var Jetpack
1214 + */
1215 + var $jetpack = null;
1216 +
1217 + /**
1218 + * Holds the singleton instance of this class
1219 + *
1220 + * @since 2.3.3
1221 + * @var Jetpack_Heartbeat
1222 + */
1223 + static $instance = false;
1224 +
1225 + private $cron_name = 'jetpack_heartbeat';
1226 +
1227 + /**
1228 + * Singleton
1229 + *
1230 + * @since 2.3.3
1231 + * @static
1232 + * @return Jetpack_Heartbeat
1233 + */
1234 + public static function init() {
1235 + if ( ! self::$instance ) {
1236 + self::$instance = new Jetpack_Heartbeat;
1237 + }
1238 +
1239 + return self::$instance;
1240 + }
1241 +
1242 + /**
1243 + * Constructor for singleton
1244 + *
1245 + * @since 2.3.3
1246 + * @return Jetpack_Heartbeat
1247 + */
1248 + private function __construct() {
1249 + $this->jetpack = Jetpack::init();
1250 +
1251 + // Add weekly interval for wp-cron
1252 + add_filter('cron_schedules', array( $this, 'add_cron_intervals' ) );
1253 +
1254 + // Schedule the task
1255 + add_action( $this->cron_name, array( $this, 'cron_exec' ) );
1256 +
1257 + if (!wp_next_scheduled( $this->cron_name ) ) {
1258 + wp_schedule_event( time(), 'jetpack_weekly', $this->cron_name );
1259 + }
1260 + }
1261 +
1262 + /**
1263 + * Method that gets executed on the wp-cron call
1264 + *
1265 + * @since 2.3.3
1266 + * @global string $wp_version
1267 + */
1268 + public function cron_exec() {
1269 +
1270 + /*
1271 + * Check for an identity crisis
1272 + *
1273 + * If one exists:
1274 + * - Bump stat for ID crisis
1275 + * - Email site admin about potential ID crisis
1276 + */
1277 +
1278 +
1279 +
1280 + /**
1281 + * Setup an array of items that will eventually be stringified
1282 + * and sent off to the Jetpack API
1283 + *
1284 + * Associative array with format group => values
1285 + * - values should be an array that will be imploded to a string
1286 + */
1287 +
1288 + $jetpack = $this->jetpack;
1289 +
1290 + $jetpack->stat( 'active-modules', implode( ',', $this->jetpack->get_active_modules() ) );
1291 + $jetpack->stat( 'active', JETPACK__VERSION );
1292 + $jetpack->stat( 'wp-version', get_bloginfo( 'version' ) );
1293 + $jetpack->stat( 'php-version', PHP_VERSION );
1294 + $jetpack->stat( 'ssl', $jetpack->permit_ssl() );
1295 + $jetpack->stat( 'language', get_bloginfo( 'language' ) );
1296 + $jetpack->stat( 'charset', get_bloginfo( 'charset' ) );
1297 + $jetpack->stat( 'qty-posts', wp_count_posts()->publish );
1298 + $jetpack->stat( 'qty-pages', wp_count_posts( 'page' )->publish );
1299 + $jetpack->stat( 'qty-comments', wp_count_comments()->approved );
1300 + $jetpack->stat( 'is-multisite', is_multisite() ? 'multisite' : 'singlesite' );
1301 +
1302 + // Only check a few plugins, to see if they're currently active.
1303 + $plugins_to_check = array(
1304 + 'vaultpress/vaultpress.php',
1305 + 'akismet/akismet.php',
1306 + 'wp-super-cache/wp-cache.php',
1307 + );
1308 + $plugins = array_intersect( $plugins_to_check, get_option( 'active_plugins', array() ) );
1309 + foreach( $plugins as $plugin ) {
1310 + $jetpack->stat( 'plugins', $plugin );
1311 + }
1312 +
1313 + $jetpack->do_stats( 'server_side' );
1314 + }
1315 +
1316 + /**
1317 + * Adds additional Jetpack specific intervals to wp-cron
1318 + *
1319 + * @since 2.3.3
1320 + * @return array
1321 + */
1322 + public function add_cron_intervals( $schedules ) {
1323 + $schedules['jetpack_weekly'] = array(
1324 + 'interval' => WEEK_IN_SECONDS,
1325 + 'display' => __('Jetpack weekly')
1326 + );
1327 + return $schedules;
1328 + }
1329 +
1330 + public function deactivate() {
1331 + $timestamp = wp_next_scheduled( $this->cron_name );
1332 + wp_unschedule_event($timestamp, $this->cron_name );
1333 + }
1334 +
1335 +}// end class
1336
1337 diff --git a/plugins/jetpack/class.jetpack-options.php b/plugins/jetpack/class.jetpack-options.php
1338 new file mode 100644
1339 index 0000000..f480f30
1340 --- /dev/null
1341 +++ b/plugins/jetpack/class.jetpack-options.php
1342 @@ -0,0 +1,143 @@
1343 +<?php
1344 +
1345 +class Jetpack_Options {
1346 +
1347 + public static function get_option_names( $type = 'compact' ) {
1348 + switch ( $type ) {
1349 + case 'non-compact' :
1350 + case 'non_compact' :
1351 + return array(
1352 + 'register',
1353 + 'activated',
1354 + 'active_modules',
1355 + 'do_activate',
1356 + 'publicize',
1357 + 'widget_twitter',
1358 + );
1359 + }
1360 +
1361 + return array(
1362 + 'id', // (int) The Client ID/WP.com Blog ID of this site.
1363 + 'blog_token', // (string) The Client Secret/Blog Token of this site.
1364 + 'user_token', // (string) The User Token of this site. (deprecated)
1365 + 'publicize_connections', // (array) An array of Publicize connections from WordPress.com
1366 + 'master_user', // (int) The local User ID of the user who connected this site to jetpack.wordpress.com.
1367 + 'user_tokens', // (array) User Tokens for each user of this site who has connected to jetpack.wordpress.com.
1368 + 'version', // (string) Used during upgrade procedure to auto-activate new modules. version:time
1369 + 'old_version', // (string) Used to determine which modules are the most recently added. previous_version:time
1370 + 'fallback_no_verify_ssl_certs', // (int) Flag for determining if this host must skip SSL Certificate verification due to misconfigured SSL.
1371 + 'time_diff', // (int) Offset between Jetpack server's clocks and this server's clocks. Jetpack Server Time = time() + (int) Jetpack_Options::get_option( 'time_diff' )
1372 + 'public', // (int|bool) If we think this site is public or not (1, 0), false if we haven't yet tried to figure it out.
1373 + 'is_network_site', // (int|bool) If we think this site is a network or a single blog (1, 0), false if we haven't yet tried to figue it out.
1374 + 'social_links', // (array) The specified links for each social networking site.
1375 + );
1376 + }
1377 +
1378 + /**
1379 + * Returns the requested option. Looks in jetpack_options or jetpack_$name as appropriate.
1380 + *
1381 + * @param string $name Option name
1382 + * @param mixed $default (optional)
1383 + */
1384 + public static function get_option( $name, $default = false ) {
1385 + if ( in_array( $name, self::get_option_names( 'non_compact' ) ) ) {
1386 + return get_option( "jetpack_$name" );
1387 + } else if ( !in_array( $name, self::get_option_names() ) ) {
1388 + trigger_error( sprintf( 'Invalid Jetpack option name: %s', $name ), E_USER_WARNING );
1389 + return false;
1390 + }
1391 +
1392 + $options = get_option( 'jetpack_options' );
1393 + if ( is_array( $options ) && isset( $options[$name] ) ) {
1394 + return $options[$name];
1395 + }
1396 +
1397 + return $default;
1398 + }
1399 +
1400 + /**
1401 + * Updates the single given option. Updates jetpack_options or jetpack_$name as appropriate.
1402 + *
1403 + * @param string $name Option name
1404 + * @param mixed $value Option value
1405 + */
1406 + public static function update_option( $name, $value ) {
1407 + if ( in_array( $name, self::get_option_names( 'non_compact' ) ) ) {
1408 + return update_option( "jetpack_$name", $value );
1409 + } else if ( !in_array( $name, self::get_option_names() ) ) {
1410 + trigger_error( sprintf( 'Invalid Jetpack option name: %s', $name ), E_USER_WARNING );
1411 + return false;
1412 + }
1413 +
1414 + $options = get_option( 'jetpack_options' );
1415 + if ( !is_array( $options ) ) {
1416 + $options = array();
1417 + }
1418 +
1419 + $options[$name] = $value;
1420 +
1421 + return update_option( 'jetpack_options', $options );
1422 + }
1423 +
1424 + /**
1425 + * Updates the multiple given options. Updates jetpack_options and/or jetpack_$name as appropriate.
1426 + *
1427 + * @param array $array array( option name => option value, ... )
1428 + */
1429 + public static function update_options( $array ) {
1430 + $names = array_keys( $array );
1431 +
1432 + foreach ( array_diff( $names, self::get_option_names(), self::get_option_names( 'non_compact' ) ) as $unknown_name ) {
1433 + trigger_error( sprintf( 'Invalid Jetpack option name: %s', $unknown_name ), E_USER_WARNING );
1434 + unset( $array[$unknown_name] );
1435 + }
1436 +
1437 + foreach ( array_intersect( $names, self::get_option_names( 'non_compact' ) ) as $name ) {
1438 + update_option( "jetpack_$name", $array[$name] );
1439 + unset( $array[$name] );
1440 + }
1441 +
1442 + $options = get_option( 'jetpack_options' );
1443 + if ( !is_array( $options ) ) {
1444 + $options = array();
1445 + }
1446 +
1447 + return update_option( 'jetpack_options', array_merge( $options, $array ) );
1448 + }
1449 +
1450 + /**
1451 + * Deletes the given option. May be passed multiple option names as an array.
1452 + * Updates jetpack_options and/or deletes jetpack_$name as appropriate.
1453 + *
1454 + * @param string|array $names
1455 + */
1456 + public static function delete_option( $names ) {
1457 + $names = (array) $names;
1458 +
1459 + foreach ( array_diff( $names, self::get_option_names(), self::get_option_names( 'non_compact' ) ) as $unknown_name ) {
1460 + trigger_error( sprintf( 'Invalid Jetpack option name: %s', $unknown_name ), E_USER_WARNING );
1461 + }
1462 +
1463 + foreach ( array_intersect( $names, self::get_option_names( 'non_compact' ) ) as $name ) {
1464 + delete_option( "jetpack_$name" );
1465 + }
1466 +
1467 + $options = get_option( 'jetpack_options' );
1468 + if ( !is_array( $options ) ) {
1469 + $options = array();
1470 + }
1471 +
1472 + $to_delete = array_intersect( $names, self::get_option_names(), array_keys( $options ) );
1473 + if ( $to_delete ) {
1474 + foreach ( $to_delete as $name ) {
1475 + unset( $options[$name] );
1476 + }
1477 +
1478 + return update_option( 'jetpack_options', $options );
1479 + }
1480 +
1481 + return true;
1482 + }
1483 +
1484 +}
1485 +
1486
1487 diff --git a/plugins/jetpack/class.jetpack-sync.php b/plugins/jetpack/class.jetpack-sync.php
1488 new file mode 100644
1489 index 0000000..2ff9dfb
1490 --- /dev/null
1491 +++ b/plugins/jetpack/class.jetpack-sync.php
1492 @@ -0,0 +1,713 @@
1493 +<?php
1494 +
1495 +/**
1496 + * Request that a piece of data on this WordPress install be synced back to the
1497 + * Jetpack server for remote processing/notifications/etc
1498 + */
1499 +class Jetpack_Sync {
1500 + // What modules want to sync what content
1501 + var $sync_conditions = array( 'posts' => array(), 'comments' => array() );
1502 +
1503 + // We keep track of all the options registered for sync so that we can sync them all if needed
1504 + var $sync_options = array();
1505 +
1506 + // Keep trac of status transitions, which we wouldn't always know about on the Jetpack Servers but are important when deciding what to do with the sync.
1507 + var $post_transitions = array();
1508 + var $comment_transitions = array();
1509 +
1510 + // Objects to sync
1511 + var $sync = array();
1512 +
1513 + function __construct() {
1514 + // WP Cron action. Only used on upgrade
1515 + add_action( 'jetpack_sync_all_registered_options', array( $this, 'sync_all_registered_options' ) );
1516 + }
1517 +
1518 +/* Static Methods for Modules */
1519 +
1520 + /**
1521 + * @param string $file __FILE__
1522 + * @param array settings:
1523 + * post_types => array( post_type slugs ): The post types to sync. Default: post, page
1524 + * post_stati => array( post_status slugs ): The post stati to sync. Default: publish
1525 + */
1526 + static function sync_posts( $file, array $settings = null ) {
1527 + $jetpack = Jetpack::init();
1528 + $args = func_get_args();
1529 + return call_user_func_array( array( $jetpack->sync, 'posts' ), $args );
1530 + }
1531 +
1532 + /**
1533 + * @param string $file __FILE__
1534 + * @param array settings:
1535 + * post_types => array( post_type slugs ): The post types to sync. Default: post, page
1536 + * post_stati => array( post_status slugs ): The post stati to sync. Default: publish
1537 + * comment_types => array( comment_type slugs ): The comment types to sync. Default: '', comment, trackback, pingback
1538 + * comment_stati => array( comment_status slugs ): The comment stati to sync. Default: approved
1539 + */
1540 + static function sync_comments( $file, array $settings = null ) {
1541 + $jetpack = Jetpack::init();
1542 + $args = func_get_args();
1543 + return call_user_func_array( array( $jetpack->sync, 'comments' ), $args );
1544 + }
1545 +
1546 + /**
1547 + * @param string $file __FILE__
1548 + * @param string $option, Option name to sync
1549 + * @param string $option ...
1550 + */
1551 + static function sync_options( $file, $option /*, $option, ... */ ) {
1552 + $jetpack = Jetpack::init();
1553 + $args = func_get_args();
1554 + return call_user_func_array( array( $jetpack->sync, 'options' ), $args );
1555 + }
1556 +
1557 +/* Internal Methods */
1558 +
1559 + /**
1560 + * Create a sync object/request
1561 + *
1562 + * @param string $object Type of object to sync -- [ post | comment | option ]
1563 + * @param int $id Unique identifier
1564 + * @param array $settings
1565 + */
1566 + function register( $object, $id = false, array $settings = null ) {
1567 + // Since we've registered something for sync, hook it up to execute on shutdown if we haven't already
1568 + if ( !$this->sync ) {
1569 + ignore_user_abort( true );
1570 + add_action( 'shutdown', array( $this, 'sync' ), 9 ); // Right before async XML-RPC
1571 + }
1572 +
1573 + $defaults = array(
1574 + 'on_behalf_of' => array(), // What modules want this data
1575 + );
1576 + $settings = wp_parse_args( $settings, $defaults );
1577 +
1578 + if ( !isset( $this->sync[$object] ) ) {
1579 + $this->sync[$object] = array();
1580 + }
1581 +
1582 + // Store the settings for this object
1583 + if (
1584 + // First time for this object
1585 + !isset( $this->sync[$object][$id] )
1586 + ) {
1587 + // Easy: store the current settings
1588 + $this->sync[$object][$id] = $settings;
1589 + } else {
1590 + // Not as easy: we have to manually merge the settings from previous runs for this object with the settings for this run
1591 +
1592 + $this->sync[$object][$id]['on_behalf_of'] = array_unique( array_merge( $this->sync[$object][$id]['on_behalf_of'], $settings['on_behalf_of'] ) );
1593 + }
1594 +
1595 + $delete_prefix = 'delete_';
1596 + if ( 0 === strpos( $object, $delete_prefix ) ) {
1597 + $unset_object = substr( $object, strlen( $delete_prefix ) );
1598 + } else {
1599 + $unset_object = "{$delete_prefix}{$object}";
1600 + }
1601 +
1602 + // Ensure post ... delete_post yields a delete operation
1603 + // Ensure delete_post ... post yields a sync post operation
1604 + // Ensure update_option() ... delete_option() ends up as a delete
1605 + // Ensure delete_option() ... update_option() ends up as an update
1606 + // Etc.
1607 + unset( $this->sync[$unset_object][$id] );
1608 +
1609 + return true;
1610 + }
1611 +
1612 + function get_common_sync_data() {
1613 + $available_modules = Jetpack::get_available_modules();
1614 + $active_modules = Jetpack::get_active_modules();
1615 + $modules = array();
1616 + foreach ( $available_modules as $available_module ) {
1617 + $modules[$available_module] = in_array( $available_module, $active_modules );
1618 + }
1619 + $modules['vaultpress'] = class_exists( 'VaultPress' ) || function_exists( 'vaultpress_contact_service' );
1620 +
1621 + $sync_data = array(
1622 + 'modules' => $modules,
1623 + 'version' => JETPACK__VERSION,
1624 + );
1625 +
1626 + return $sync_data;
1627 + }
1628 +
1629 + /**
1630 + * Set up all the data and queue it for the outgoing XML-RPC request
1631 + */
1632 + function sync() {
1633 + if ( !$this->sync ) {
1634 + return false;
1635 + }
1636 +
1637 + $sync_data = $this->get_common_sync_data();
1638 +
1639 + $wp_importing = defined( 'WP_IMPORTING' ) && WP_IMPORTING;
1640 +
1641 + foreach ( $this->sync as $sync_operation_type => $sync_operations ) {
1642 + switch ( $sync_operation_type ) {
1643 + case 'post':
1644 + if ( $wp_importing ) {
1645 + break;
1646 + }
1647 +
1648 + $global_post = isset( $GLOBALS['post'] ) ? $GLOBALS['post'] : null;
1649 + $GLOBALS['post'] = null;
1650 + foreach ( $sync_operations as $post_id => $settings ) {
1651 + $sync_data['post'][$post_id] = $this->get_post( $post_id );
1652 + if ( isset( $this->post_transitions[$post_id] ) ) {
1653 + $sync_data['post'][$post_id]['transitions'] = $this->post_transitions[$post_id];
1654 + } else {
1655 + $sync_data['post'][$post_id]['transitions'] = array( false, false );
1656 + }
1657 + $sync_data['post'][$post_id]['on_behalf_of'] = $settings['on_behalf_of'];
1658 + }
1659 + $GLOBALS['post'] = $global_post;
1660 + unset( $global_post );
1661 + break;
1662 + case 'comment':
1663 + if ( $wp_importing ) {
1664 + break;
1665 + }
1666 +
1667 + $global_comment = isset( $GLOBALS['comment'] ) ? $GLOBALS['comment'] : null;
1668 + unset( $GLOBALS['comment'] );
1669 + foreach ( $sync_operations as $comment_id => $settings ) {
1670 + $sync_data['comment'][$comment_id] = $this->get_comment( $comment_id );
1671 + if ( isset( $this->comment_transitions[$comment_id] ) ) {
1672 + $sync_data['comment'][$comment_id]['transitions'] = $this->comment_transitions[$comment_id];
1673 + } else {
1674 + $sync_data['comment'][$comment_id]['transitions'] = array( false, false );
1675 + }
1676 + $sync_data['comment'][$comment_id]['on_behalf_of'] = $settings['on_behalf_of'];
1677 + }
1678 + $GLOBALS['comment'] = $global_comment;
1679 + unset( $global_comment );
1680 + break;
1681 + case 'option' :
1682 + foreach ( $sync_operations as $option => $settings ) {
1683 + $sync_data['option'][$option] = array( 'value' => get_option( $option ) );
1684 + }
1685 + break;
1686 +
1687 + case 'delete_post':
1688 + case 'delete_comment':
1689 + foreach ( $sync_operations as $object_id => $settings ) {
1690 + $sync_data[$sync_operation_type][$object_id] = array( 'on_behalf_of' => $settings['on_behalf_of'] );
1691 + }
1692 + break;
1693 + case 'delete_option' :
1694 + foreach ( $sync_operations as $object_id => $settings ) {
1695 + $sync_data[$sync_operation_type][$object_id] = true;
1696 + }
1697 + break;
1698 + }
1699 + }
1700 +
1701 + Jetpack::xmlrpc_async_call( 'jetpack.syncContent', $sync_data );
1702 + }
1703 +
1704 + /**
1705 + * Format and return content data from a direct xmlrpc request for it.
1706 + *
1707 + * @param array $content_ids: array( 'posts' => array of ids, 'comments' => array of ids, 'options' => array of options )
1708 + */
1709 + function get_content( $content_ids ) {
1710 + $sync_data = $this->get_common_sync_data();
1711 +
1712 + if ( isset( $content_ids['posts'] ) ) {
1713 + foreach ( $content_ids['posts'] as $id ) {
1714 + $sync_data['post'][$id] = $this->get_post( $id );
1715 + }
1716 + }
1717 +
1718 + if ( isset( $content_ids['comments'] ) ) {
1719 + foreach ( $content_ids['comments'] as $id ) {
1720 + $sync_data['comment'][$id] = $this->get_post( $id );
1721 + }
1722 + }
1723 +
1724 + if ( isset( $content_ids['options'] ) ) {
1725 + foreach ( $content_ids['options'] as $option ) {
1726 + $sync_data['option'][$option] = array( 'value' => get_option( $option ) );
1727 + }
1728 + }
1729 +
1730 + return $sync_data;
1731 + }
1732 +
1733 + /**
1734 + * Helper method for registering a post for sync
1735 + *
1736 + * @param int $id wp_posts.ID
1737 + * @param array $settings Sync data
1738 + */
1739 + function register_post( $id, array $settings = null ) {
1740 + $id = (int) $id;
1741 + if ( !$id ) {
1742 + return false;
1743 + }
1744 +
1745 + $post = get_post( $id );
1746 + if ( !$post ) {
1747 + return false;
1748 + }
1749 +
1750 + $settings = wp_parse_args( $settings, array(
1751 + 'on_behalf_of' => array(),
1752 + ) );
1753 +
1754 + return $this->register( 'post', $id, $settings );
1755 + }
1756 +
1757 + /**
1758 + * Helper method for registering a comment for sync
1759 + *
1760 + * @param int $id wp_comments.comment_ID
1761 + * @param array $settings Sync data
1762 + */
1763 + function register_comment( $id, array $settings = null ) {
1764 + $id = (int) $id;
1765 + if ( !$id ) {
1766 + return false;
1767 + }
1768 +
1769 + $comment = get_comment( $id );
1770 + if ( !$comment || empty( $comment->comment_post_ID ) ) {
1771 + return false;
1772 + }
1773 +
1774 + $post = get_post( $comment->comment_post_ID );
1775 + if ( !$post ) {
1776 + return false;
1777 + }
1778 +
1779 + $settings = wp_parse_args( $settings, array(
1780 + 'on_behalf_of' => array(),
1781 + ) );
1782 +
1783 + return $this->register( 'comment', $id, $settings );
1784 + }
1785 +
1786 +/* Posts Sync */
1787 +
1788 + function posts( $file, array $settings = null ) {
1789 + $module_slug = Jetpack::get_module_slug( $file );
1790 +
1791 + $defaults = array(
1792 + 'post_types' => array( 'post', 'page' ),
1793 + 'post_stati' => array( 'publish' ),
1794 + );
1795 +
1796 + $this->sync_conditions['posts'][$module_slug] = wp_parse_args( $settings, $defaults );
1797 +
1798 + add_action( 'transition_post_status', array( $this, 'transition_post_status_action' ), 10, 3 );
1799 + add_action( 'delete_post', array( $this, 'delete_post_action' ) );
1800 + }
1801 +
1802 + function delete_post_action( $post_id ) {
1803 + $post = get_post( $post_id );
1804 + if ( !$post ) {
1805 + return $this->register( 'delete_post', (int) $post_id );
1806 + }
1807 +
1808 + $this->transition_post_status_action( 'delete', $post->post_status, $post );
1809 + }
1810 +
1811 + function transition_post_status_action( $new_status, $old_status, $post ) {
1812 + $sync = $this->get_post_sync_operation( $new_status, $old_status, $post, $this->sync_conditions['posts'] );
1813 + if ( !$sync ) {
1814 + // No module wants to sync this post
1815 + return false;
1816 + }
1817 +
1818 + // Track post transitions
1819 + if ( isset( $this->post_transitions[$post->ID] ) ) {
1820 + // status changed more than once - keep tha most recent $new_status
1821 + $this->post_transitions[$post->ID][0] = $new_status;
1822 + } else {
1823 + $this->post_transitions[$post->ID] = array( $new_status, $old_status );
1824 + }
1825 +
1826 + $operation = $sync['operation'];
1827 + unset( $sync['operation'] );
1828 +
1829 + switch ( $operation ) {
1830 + case 'delete' :
1831 + return $this->register( 'delete_post', (int) $post->ID, $sync );
1832 + case 'submit' :
1833 + return $this->register_post( (int) $post->ID, $sync );
1834 + }
1835 + }
1836 +
1837 + function get_post_sync_operation( $new_status, $old_status, $post, $module_conditions ) {
1838 + $delete_on_behalf_of = array();
1839 + $submit_on_behalf_of = array();
1840 + $delete_stati = array( 'delete' );
1841 +
1842 + foreach ( $module_conditions as $module => $conditions ) {
1843 + if ( !in_array( $post->post_type, $conditions['post_types'] ) ) {
1844 + continue;
1845 + }
1846 +
1847 + $deleted_post = in_array( $new_status, $delete_stati );
1848 +
1849 + if ( $deleted_post ) {
1850 + $delete_on_behalf_of[] = $module;
1851 + } else {
1852 + clean_post_cache( $post->ID );
1853 + $new_status = get_post_status( $post->ID ); // Inherited status is resolved here
1854 + }
1855 +
1856 + $old_status_in_stati = in_array( $old_status, $conditions['post_stati'] );
1857 + $new_status_in_stati = in_array( $new_status, $conditions['post_stati'] );
1858 +
1859 + if ( $old_status_in_stati && !$new_status_in_stati ) {
1860 + // Jetpack no longer needs the post
1861 + if ( !$deleted_post ) {
1862 + $delete_on_behalf_of[] = $module;
1863 + } // else, we've already flagged it above
1864 + continue;
1865 + }
1866 +
1867 + if ( !$new_status_in_stati ) {
1868 + continue;
1869 + }
1870 +
1871 + // At this point, we know we want to sync the post, not delete it
1872 + $submit_on_behalf_of[] = $module;
1873 + }
1874 +
1875 + if ( !empty( $submit_on_behalf_of ) ) {
1876 + return array( 'operation' => 'submit', 'on_behalf_of' => $submit_on_behalf_of );
1877 + }
1878 +
1879 + if ( !empty( $delete_on_behalf_of ) ) {
1880 + return array( 'operation' => 'delete', 'on_behalf_of' => $delete_on_behalf_of );
1881 + }
1882 +
1883 + return false;
1884 + }
1885 +
1886 + /**
1887 + * Get a post and associated data in the standard JP format.
1888 + * Cannot be called statically
1889 + *
1890 + * @param int $id Post ID
1891 + * @return Array containing full post details
1892 + */
1893 + function get_post( $id ) {
1894 + $post_obj = get_post( $id );
1895 + if ( !$post_obj )
1896 + return false;
1897 +
1898 + if ( is_callable( $post_obj, 'to_array' ) ) {
1899 + // WP >= 3.5
1900 + $post = $post_obj->to_array();
1901 + } else {
1902 + // WP < 3.5
1903 + $post = get_object_vars( $post_obj );
1904 + }
1905 +
1906 + if ( 0 < strlen( $post['post_password'] ) ) {
1907 + $post['post_password'] = 'auto-' . wp_generate_password( 10, false ); // We don't want the real password. Just pass something random.
1908 + }
1909 +
1910 + // local optimizations
1911 + unset(
1912 + $post['filter'],
1913 + $post['ancestors'],
1914 + $post['post_content_filtered'],
1915 + $post['to_ping'],
1916 + $post['pinged']
1917 + );
1918 +
1919 + if ( $this->is_post_public( $post ) ) {
1920 + $post['post_is_public'] = Jetpack::get_option( 'public' );
1921 + } else {
1922 + //obscure content
1923 + $post['post_content'] = '';
1924 + $post['post_excerpt'] = '';
1925 + $post['post_is_public'] = false;
1926 + }
1927 + $post_type_obj = get_post_type_object( $post['post_type'] );
1928 + $post['post_is_excluded_from_search'] = $post_type_obj->exclude_from_search;
1929 +
1930 + $post['tax'] = array();
1931 + $taxonomies = get_object_taxonomies( $post_obj );
1932 + foreach ( $taxonomies as $taxonomy ) {
1933 + $terms = get_object_term_cache( $post_obj->ID, $taxonomy );
1934 + if ( empty( $terms ) )
1935 + $terms = wp_get_object_terms( $post_obj->ID, $taxonomy );
1936 + $term_names = array();
1937 + foreach ( $terms as $term ) {
1938 + $term_names[] = $term->name;
1939 + }
1940 + $post['tax'][$taxonomy] = $term_names;
1941 + }
1942 +
1943 + $meta = get_post_meta( $post_obj->ID, false );
1944 + $post['meta'] = array();
1945 + foreach ( $meta as $key => $value ) {
1946 + $post['meta'][$key] = array_map( 'maybe_unserialize', $value );
1947 + }
1948 +
1949 + $post['extra'] = array(
1950 + 'author' => get_the_author_meta( 'display_name', $post_obj->post_author ),
1951 + 'author_email' => get_the_author_meta( 'email', $post_obj->post_author ),
1952 + );
1953 +
1954 + if ( $fid = get_post_thumbnail_id( $id ) ) {
1955 + $feature = wp_get_attachment_image_src( $fid, 'large' );
1956 + if ( !empty( $feature[0] ) )
1957 + $post['extra']['featured_image'] = $feature[0];
1958 + }
1959 +
1960 + $post['permalink'] = get_permalink( $post_obj->ID );
1961 + $post['shortlink'] = wp_get_shortlink( $post_obj->ID );
1962 + return $post;
1963 + }
1964 +
1965 + /**
1966 + * Decide whether a post/page/attachment is visible to the public.
1967 + *
1968 + * @param array $post
1969 + * @return bool
1970 + */
1971 + function is_post_public( $post ) {
1972 + if ( !is_array( $post ) ) {
1973 + $post = (array) $post;
1974 + }
1975 +
1976 + if ( 0 < strlen( $post['post_password'] ) )
1977 + return false;
1978 + if ( ! in_array( $post['post_type'], get_post_types( array( 'public' => true ) ) ) )
1979 + return false;
1980 + $post_status = get_post_status( $post['ID'] ); // Inherited status is resolved here.
1981 + if ( ! in_array( $post_status, get_post_stati( array( 'public' => true ) ) ) )
1982 + return false;
1983 + return true;
1984 + }
1985 +
1986 +/* Comments Sync */
1987 +
1988 + function comments( $file, array $settings = null ) {
1989 + $module_slug = Jetpack::get_module_slug( $file );
1990 +
1991 + $defaults = array(
1992 + 'post_types' => array( 'post', 'page' ), // For what post types will we sync comments?
1993 + 'post_stati' => array( 'publish' ), // For what post stati will we sync comments?
1994 + 'comment_types' => array( '', 'comment', 'trackback', 'pingback' ), // What comment types will we sync?
1995 + 'comment_stati' => array( 'approved' ), // What comment stati will we sync?
1996 + );
1997 +
1998 + $settings = wp_parse_args( $settings, $defaults );
1999 +
2000 + $this->sync_conditions['comments'][$module_slug] = $settings;
2001 +
2002 + add_action( 'wp_insert_comment', array( $this, 'wp_insert_comment_action' ), 10, 2 );
2003 + add_action( 'transition_comment_status', array( $this, 'transition_comment_status_action' ), 10, 3 );
2004 + add_action( 'edit_comment', array( $this, 'edit_comment_action' ) );
2005 + }
2006 +
2007 + /*
2008 + * This is really annoying. If you edit a comment, but don't change the status, WordPress doesn't fire the transition_comment_status hook.
2009 + * That means we have to catch these comments on the edit_comment hook, but ignore comments on that hook when the transition_comment_status does fire.
2010 + */
2011 + function edit_comment_action( $comment_id ) {
2012 + $comment = get_comment( $comment_id );
2013 + $new_status = $this->translate_comment_status( $comment->comment_approved );
2014 + add_action( "comment_{$new_status}_{$comment->comment_type}", array( $this, 'transition_comment_status_for_comments_whose_status_does_not_change' ), 10, 2 );
2015 + }
2016 +
2017 + function wp_insert_comment_action( $comment_id, $comment ) {
2018 + $this->transition_comment_status_action( $comment->comment_approved, 'new', $comment );
2019 + }
2020 +
2021 + function transition_comment_status_for_comments_whose_status_does_not_change( $comment_id, $comment ) {
2022 + if ( isset( $this->comment_transitions[$comment_id] ) ) {
2023 + return $this->transition_comment_status_action( $comment->comment_approved, $this->comment_transitions[$comment_id][1], $comment );
2024 + }
2025 +
2026 + return $this->transition_comment_status_action( $comment->comment_approved, $comment->comment_approved, $comment );
2027 + }
2028 +
2029 + function translate_comment_status( $status ) {
2030 + switch ( (string) $status ) {
2031 + case '0' :
2032 + case 'hold' :
2033 + return 'unapproved';
2034 + case '1' :
2035 + case 'approve' :
2036 + return 'approved';
2037 + }
2038 +
2039 + return $status;
2040 + }
2041 +
2042 + function transition_comment_status_action( $new_status, $old_status, $comment ) {
2043 + $post = get_post( $comment->comment_post_ID );
2044 + if ( !$post ) {
2045 + return false;
2046 + }
2047 +
2048 + foreach ( array( 'new_status', 'old_status' ) as $_status ) {
2049 + $$_status = $this->translate_comment_status( $$_status );
2050 + }
2051 +
2052 + // Track comment transitions
2053 + if ( isset( $this->comment_transitions[$comment->comment_ID] ) ) {
2054 + // status changed more than once - keep tha most recent $new_status
2055 + $this->comment_transitions[$comment->comment_ID][0] = $new_status;
2056 + } else {
2057 + $this->comment_transitions[$comment->comment_ID] = array( $new_status, $old_status );
2058 + }
2059 +
2060 + $post_sync = $this->get_post_sync_operation( $post->post_status, '_jetpack_test_sync', $post, $this->sync_conditions['comments'] );
2061 +
2062 + if ( !$post_sync ) {
2063 + // No module wants to sync this comment because its post doesn't match any sync conditions
2064 + return false;
2065 + }
2066 +
2067 + if ( 'delete' == $post_sync['operation'] ) {
2068 + // Had we been looking at post sync operations (instead of comment sync operations),
2069 + // this comment's post would have been deleted. Don't sync the comment.
2070 + return false;
2071 + }
2072 +
2073 + $delete_on_behalf_of = array();
2074 + $submit_on_behalf_of = array();
2075 + $delete_stati = array( 'delete' );
2076 +
2077 + foreach ( $this->sync_conditions['comments'] as $module => $conditions ) {
2078 + if ( !in_array( $comment->comment_type, $conditions['comment_types'] ) ) {
2079 + continue;
2080 + }
2081 +
2082 + $deleted_comment = in_array( $new_status, $delete_stati );
2083 +
2084 + if ( $deleted_comment ) {
2085 + $delete_on_behalf_of[] = $module;
2086 + }
2087 +
2088 + $old_status_in_stati = in_array( $old_status, $conditions['comment_stati'] );
2089 + $new_status_in_stati = in_array( $new_status, $conditions['comment_stati'] );
2090 +
2091 + if ( $old_status_in_stati && !$new_status_in_stati ) {
2092 + // Jetpack no longer needs the comment
2093 + if ( !$deleted_comment ) {
2094 + $delete_on_behalf_of[] = $module;
2095 + } // else, we've already flagged it above
2096 + continue;
2097 + }
2098 +
2099 + if ( !$new_status_in_stati ) {
2100 + continue;
2101 + }
2102 +
2103 + // At this point, we know we want to sync the comment, not delete it
2104 + $submit_on_behalf_of[] = $module;
2105 + }
2106 +
2107 + if ( ! empty( $submit_on_behalf_of ) ) {
2108 + $this->register_post( $comment->comment_post_ID, array( 'on_behalf_of' => $submit_on_behalf_of ) );
2109 + return $this->register_comment( $comment->comment_ID, array( 'on_behalf_of' => $submit_on_behalf_of ) );
2110 + }
2111 +
2112 + if ( !empty( $delete_on_behalf_of ) ) {
2113 + return $this->register( 'delete_comment', $comment->comment_ID, array( 'on_behalf_of' => $delete_on_behalf_of ) );
2114 + }
2115 +
2116 + return false;
2117 + }
2118 +
2119 + /**
2120 + * Get a comment and associated data in the standard JP format.
2121 + * Cannot be called statically
2122 + *
2123 + * @param int $id Comment ID
2124 + * @return Array containing full comment details
2125 + */
2126 + function get_comment( $id ) {
2127 + $comment_obj = get_comment( $id );
2128 + if ( !$comment_obj )
2129 + return false;
2130 + $comment = get_object_vars( $comment_obj );
2131 +
2132 + $meta = get_comment_meta( $id, false );
2133 + $comment['meta'] = array();
2134 + foreach ( $meta as $key => $value ) {
2135 + $comment['meta'][$key] = array_map( 'maybe_unserialize', $value );
2136 + }
2137 +
2138 + return $comment;
2139 + }
2140 +
2141 +/* Options Sync */
2142 +
2143 + /* Ah... so much simpler than Posts and Comments :) */
2144 + function options( $file, $option /*, $option, ... */ ) {
2145 + $options = func_get_args();
2146 + $file = array_shift( $options );
2147 +
2148 + $module_slug = Jetpack::get_module_slug( $file );
2149 +
2150 + if ( !isset( $this->sync_options[$module_slug] ) ) {
2151 + $this->sync_options[$module_slug] = array();
2152 + }
2153 +
2154 + foreach ( $options as $option ) {
2155 + $this->sync_options[$module_slug][] = $option;
2156 + add_action( "delete_option_{$option}", array( $this, 'deleted_option_action' ) );
2157 + add_action( "update_option_{$option}", array( $this, 'updated_option_action' ) );
2158 + add_action( "add_option_{$option}", array( $this, 'added_option_action' ) );
2159 + }
2160 +
2161 + $this->sync_options[$module_slug] = array_unique( $this->sync_options[$module_slug] );
2162 + }
2163 +
2164 + function deleted_option_action( $option ) {
2165 + $this->register( 'delete_option', $option );
2166 + }
2167 +
2168 + function updated_option_action( $old_value ) {
2169 + // The value of $option isn't passed to the filter
2170 + // Calculate it
2171 + $option = current_filter();
2172 + $prefix = 'update_option_';
2173 + if ( 0 !== strpos( $option, $prefix ) ) {
2174 + return;
2175 + }
2176 + $option = substr( $option, strlen( $prefix ) );
2177 +
2178 + $this->added_option_action( $option );
2179 + }
2180 +
2181 + function added_option_action( $option ) {
2182 + $this->register( 'option', $option );
2183 + }
2184 +
2185 + function sync_all_module_options( $module_slug ) {
2186 + if ( empty( $this->sync_options[$module_slug] ) ) {
2187 + return;
2188 + }
2189 +
2190 + foreach ( $this->sync_options[$module_slug] as $option ) {
2191 + $this->added_option_action( $option );
2192 + }
2193 + }
2194 +
2195 + function sync_all_registered_options( $options = array() ) {
2196 + if ( 'jetpack_sync_all_registered_options' == current_filter() ) {
2197 + $all_registered_options = array_unique( call_user_func_array( 'array_merge', $this->sync_options ) );
2198 + foreach ( $all_registered_options as $option ) {
2199 + $this->added_option_action( $option );
2200 + }
2201 + } else {
2202 + wp_schedule_single_event( time(), 'jetpack_sync_all_registered_options', array( $this->sync_options ) );
2203 + }
2204 + }
2205 +}
2206
2207 diff --git a/plugins/jetpack/class.jetpack.php b/plugins/jetpack/class.jetpack.php
2208 new file mode 100644
2209 index 0000000..229d083
2210 --- /dev/null
2211 +++ b/plugins/jetpack/class.jetpack.php
2212 @@ -0,0 +1,3684 @@
2213 +<?php
2214 +
2215 +/*
2216 +Options:
2217 +jetpack_options (array)
2218 + An array of options.
2219 + @see Jetpack::get_option_names()
2220 +
2221 +jetpack_register (string)
2222 + Temporary verification secrets.
2223 +
2224 +jetpack_activated (int)
2225 + 1: the plugin was activated normally
2226 + 2: the plugin was activated on this site because of a network-wide activation
2227 + 3: the plugin was auto-installed
2228 + 4: the plugin was manually disconnected (but is still installed)
2229 +
2230 +jetpack_active_modules (array)
2231 + Array of active module slugs.
2232 +
2233 +jetpack_do_activate (bool)
2234 + Flag for "activating" the plugin on sites where the activation hook never fired (auto-installs)
2235 +*/
2236 +
2237 +class Jetpack {
2238 + var $xmlrpc_server = null;
2239 +
2240 + var $HTTP_RAW_POST_DATA = null; // copy of $GLOBALS['HTTP_RAW_POST_DATA']
2241 +
2242 + var $plugins_to_deactivate = array(
2243 + 'stats' => array( 'stats/stats.php', 'WordPress.com Stats' ),
2244 + 'shortlinks' => array( 'stats/stats.php', 'WordPress.com Stats' ),
2245 + 'sharedaddy' => array( 'sharedaddy/sharedaddy.php', 'Sharedaddy' ),
2246 + 'twitter-widget' => array( 'wickett-twitter-widget/wickett-twitter-widget.php', 'Wickett Twitter Widget' ),
2247 + 'after-the-deadline' => array( 'after-the-deadline/after-the-deadline.php', 'After The Deadline' ),
2248 + 'contact-form' => array( 'grunion-contact-form/grunion-contact-form.php', 'Grunion Contact Form' ),
2249 + 'custom-css' => array( 'safecss/safecss.php', 'WordPress.com Custom CSS' ),
2250 + );
2251 +
2252 + var $capability_translations = array(
2253 + 'administrator' => 'manage_options',
2254 + 'editor' => 'edit_others_posts',
2255 + 'author' => 'publish_posts',
2256 + 'contributor' => 'edit_posts',
2257 + 'subscriber' => 'read',
2258 + );
2259 +
2260 + /**
2261 + * Message to display in admin_notice
2262 + * @var string
2263 + */
2264 + var $message = '';
2265 +
2266 + /**
2267 + * Error to display in admin_notice
2268 + * @var string
2269 + */
2270 + var $error = '';
2271 +
2272 + /**
2273 + * Modules that need more privacy description.
2274 + * @var string
2275 + */
2276 + var $privacy_checks = '';
2277 +
2278 + /**
2279 + * Stats to record once the page loads
2280 + *
2281 + * @var array
2282 + */
2283 + var $stats = array();
2284 +
2285 + /**
2286 + * Jetpack_Sync object
2287 + */
2288 + var $sync;
2289 +
2290 + /**
2291 + * Verified data for JSON authorization request
2292 + */
2293 + var $json_api_authorization_request = array();
2294 +
2295 + /**
2296 + * Holds the singleton instance of this class
2297 + * @since 2.3.3
2298 + * @var Jetpack
2299 + */
2300 + static $instance = false;
2301 +
2302 + /**
2303 + * Singleton
2304 + * @static
2305 + */
2306 + public static function init() {
2307 + if ( ! self::$instance ) {
2308 + if ( did_action( 'plugins_loaded' ) )
2309 + self::plugin_textdomain();
2310 + else
2311 + add_action( 'plugins_loaded', array( __CLASS__, 'plugin_textdomain' ) );
2312 +
2313 + self::$instance = new Jetpack;
2314 +
2315 + self::$instance->plugin_upgrade();
2316 + }
2317 +
2318 + return self::$instance;
2319 + }
2320 +
2321 + /**
2322 + * Must never be called statically
2323 + */
2324 + function plugin_upgrade() {
2325 + // Upgrade: 1.1 -> 1.2
2326 + if ( get_option( 'jetpack_id' ) ) {
2327 + // Move individual jetpack options to single array of options
2328 + $options = array();
2329 + foreach ( Jetpack::get_option_names() as $option ) {
2330 + if ( false !== $value = get_option( "jetpack_$option" ) ) {
2331 + $options[$option] = $value;
2332 + }
2333 + }
2334 +
2335 + if ( $options ) {
2336 + Jetpack::update_options( $options );
2337 +
2338 + foreach ( array_keys( $options ) as $option ) {
2339 + delete_option( "jetpack_$option" );
2340 + }
2341 + }
2342 +
2343 + // Add missing version and old_version options
2344 + if ( !$version = Jetpack::get_option( 'version' ) ) {
2345 + $version = $old_version = '1.1:' . time();
2346 + Jetpack::update_options( compact( 'version', 'old_version' ) );
2347 + }
2348 + }
2349 +
2350 + // Upgrade from a single user token to a user_id-indexed array and a master_user ID
2351 + if ( !Jetpack::get_option( 'user_tokens' ) ) {
2352 + if ( $user_token = Jetpack::get_option( 'user_token' ) ) {
2353 + $token_parts = explode( '.', $user_token );
2354 + if ( isset( $token_parts[2] ) ) {
2355 + $master_user = $token_parts[2];
2356 + $user_tokens = array( $master_user => $user_token );
2357 + Jetpack::update_options( compact( 'master_user', 'user_tokens' ) );
2358 + Jetpack::delete_option( 'user_token' );
2359 + } else {
2360 + // @todo: is this even possible?
2361 + trigger_error( sprintf( 'Jetpack::plugin_upgrade found no user_id in user_token "%s"', $user_token ), E_USER_WARNING );
2362 + }
2363 + }
2364 + }
2365 + }
2366 +
2367 + /**
2368 + * Constructor. Initializes WordPress hooks
2369 + */
2370 + private function Jetpack() {
2371 + $this->sync = new Jetpack_Sync;
2372 +
2373 + // Modules should do Jetpack_Sync::sync_options( __FILE__, $option, ... ); instead
2374 + // We access the "internal" method here only because the Jetpack object isn't instantiated yet
2375 + $this->sync->options( __FILE__,
2376 + 'home',
2377 + 'siteurl',
2378 + 'blogname',
2379 + 'gmt_offset',
2380 + 'timezone_string'
2381 + );
2382 +
2383 + if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST && isset( $_GET['for'] ) && 'jetpack' == $_GET['for'] ) {
2384 + @ini_set( 'display_errors', false ); // Display errors can cause the XML to be not well formed.
2385 +
2386 + require_once dirname( __FILE__ ) . '/class.jetpack-xmlrpc-server.php';
2387 + $this->xmlrpc_server = new Jetpack_XMLRPC_Server();
2388 +
2389 + $this->require_jetpack_authentication();
2390 +
2391 + if ( Jetpack::is_active() ) {
2392 + // Hack to preserve $HTTP_RAW_POST_DATA
2393 + add_filter( 'xmlrpc_methods', array( $this, 'xmlrpc_methods' ) );
2394 +
2395 + // The actual API methods.
2396 + add_filter( 'xmlrpc_methods', array( $this->xmlrpc_server, 'xmlrpc_methods' ) );
2397 + } else {
2398 + // The bootstrap API methods.
2399 + add_filter( 'xmlrpc_methods', array( $this->xmlrpc_server, 'bootstrap_xmlrpc_methods' ) );
2400 + }
2401 +
2402 + // Now that no one can authenticate, and we're whitelisting all XML-RPC methods, force enable_xmlrpc on.
2403 + add_filter( 'pre_option_enable_xmlrpc', '__return_true' );
2404 + } elseif ( is_admin() && isset( $_POST['action'] ) && 'jetpack_upload_file' == $_POST['action'] ) {
2405 + $this->require_jetpack_authentication();
2406 + $this->add_remote_request_handlers();
2407 + } else {
2408 + if ( Jetpack::is_active() ) {
2409 + add_action( 'login_form_jetpack_json_api_authorization', array( &$this, 'login_form_json_api_authorization' ) );
2410 + }
2411 + }
2412 +
2413 + add_action( 'jetpack_clean_nonces', array( 'Jetpack', 'clean_nonces' ) );
2414 + if ( !wp_next_scheduled( 'jetpack_clean_nonces' ) ) {
2415 + wp_schedule_event( time(), 'hourly', 'jetpack_clean_nonces' );
2416 + }
2417 +
2418 + add_filter( 'xmlrpc_blog_options', array( $this, 'xmlrpc_options' ) );
2419 +
2420 + add_action( 'admin_menu', array( $this, 'admin_menu' ), 999 ); // run late so that other plugins hooking into this menu don't get left out
2421 + add_action( 'admin_init', array( $this, 'admin_init' ) );
2422 + add_action( 'admin_init', array( $this, 'dismiss_jetpack_notice' ) );
2423 +
2424 + add_filter( 'admin_body_class', array( $this, 'admin_body_class' ) );
2425 +
2426 + add_action( 'wp_ajax_jetpack-check-news-subscription', array( $this, 'check_news_subscription' ) );
2427 + add_action( 'wp_ajax_jetpack-subscribe-to-news', array( $this, 'subscribe_to_news' ) );
2428 +
2429 + add_action( 'wp_loaded', array( $this, 'register_assets' ) );
2430 + add_action( 'wp_enqueue_scripts', array( $this, 'devicepx' ) );
2431 + add_action( 'customize_controls_enqueue_scripts', array( $this, 'devicepx' ) );
2432 + add_action( 'admin_enqueue_scripts', array( $this, 'devicepx' ) );
2433 +
2434 + // add_action( 'jetpack_admin_menu', array( $this, 'admin_menu_modules' ) );
2435 +
2436 + add_action( 'jetpack_activate_module', array( $this, 'activate_module_actions' ) );
2437 +
2438 + /**
2439 + * These actions run checks to load additional files.
2440 + * They check for external files or plugins, so thef need to run as late as possible.
2441 + */
2442 + add_action( 'plugins_loaded', array( $this, 'check_open_graph' ), 999 );
2443 + add_action( 'plugins_loaded', array( $this, 'check_rest_api_compat' ), 1000 );
2444 + }
2445 +
2446 + /**
2447 + * If there are any stats that need to be pushed, but haven't been, push them now.
2448 + */
2449 + function __destruct() {
2450 + if ( ! empty( $this->stats ) ) {
2451 + $this->do_stats( 'server_side' );
2452 + }
2453 + }
2454 +
2455 + function require_jetpack_authentication() {
2456 + // Don't let anyone authenticate
2457 + $_COOKIE = array();
2458 + remove_all_filters( 'authenticate' );
2459 +
2460 + if ( Jetpack::is_active() ) {
2461 + // Allow Jetpack authentication
2462 + add_filter( 'authenticate', array( $this, 'authenticate_jetpack' ), 10, 3 );
2463 + }
2464 + }
2465 +
2466 + /**
2467 + * Load language files
2468 + */
2469 + public static function plugin_textdomain() {
2470 + load_plugin_textdomain( 'jetpack', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
2471 + }
2472 +
2473 + /**
2474 + * Register assets for use in various modules and the Jetpack admin page.
2475 + *
2476 + * @uses wp_script_is, wp_register_script, plugins_url
2477 + * @action wp_loaded
2478 + * @return null
2479 + */
2480 + public function register_assets() {
2481 + if ( ! wp_script_is( 'spin', 'registered' ) )
2482 + wp_register_script( 'spin', plugins_url( '_inc/spin.js', __FILE__ ), false, '1.3' );
2483 +
2484 + if ( ! wp_script_is( 'jquery.spin', 'registered' ) )
2485 + wp_register_script( 'jquery.spin', plugins_url( '_inc/jquery.spin.js', __FILE__ ) , array( 'jquery', 'spin' ), '1.3' );
2486 +
2487 + if ( ! wp_script_is( 'jetpack-gallery-settings', 'registered' ) )
2488 + wp_register_script( 'jetpack-gallery-settings', plugins_url( '_inc/gallery-settings.js', __FILE__ ), array( 'media-views' ), '20121225' );
2489 +
2490 + if ( ! wp_style_is( 'genericons', 'registered' ) )
2491 + wp_register_style( 'genericons', plugins_url( '_inc/genericons.css', __FILE__ ), false, JETPACK__VERSION );
2492 + }
2493 +
2494 + /**
2495 + * Device Pixels support
2496 + * This improves the resolution of gravatars and wordpress.com uploads on hi-res and zoomed browsers.
2497 + */
2498 + function devicepx() {
2499 + wp_enqueue_script( 'devicepx', ( is_ssl() ? 'https' : 'http' ) . '://s0.wp.com/wp-content/js/devicepx-jetpack.js', array(), gmdate('oW'), true );
2500 + }
2501 +
2502 + /**
2503 + * Is Jetpack active?
2504 + */
2505 + public static function is_active() {
2506 + return (bool) Jetpack_Data::get_access_token( JETPACK_MASTER_USER );
2507 + }
2508 +
2509 + /**
2510 + * Is Jetpack in development (offline) mode?
2511 + */
2512 + public static function is_development_mode() {
2513 + $development_mode = false;
2514 +
2515 + if ( defined( 'JETPACK_DEV_DEBUG' ) ) {
2516 + $development_mode = JETPACK_DEV_DEBUG;
2517 + }
2518 +
2519 + elseif ( site_url() && false === strpos( site_url(), '.' ) ) {
2520 + $development_mode = true;
2521 + }
2522 +
2523 + return apply_filters( 'jetpack_development_mode', $development_mode );
2524 + }
2525 +
2526 + /**
2527 + * Is a given user (or the current user if none is specified) linked to a WordPress.com user?
2528 + */
2529 + public static function is_user_connected( $user_id = false ) {
2530 + $user_id = false === $user_id ? get_current_user_id() : absint( $user_id );
2531 + if ( !$user_id ) {
2532 + return false;
2533 + }
2534 + return (bool) Jetpack_Data::get_access_token( $user_id );
2535 + }
2536 +
2537 + function current_user_is_connection_owner() {
2538 + $user_token = Jetpack_Data::get_access_token( JETPACK_MASTER_USER );
2539 + return $user_token && is_object( $user_token ) && isset( $user_token->external_user_id ) && get_current_user_id() === $user_token->external_user_id;
2540 + }
2541 +
2542 + /**
2543 + * Synchronize connected user role changes
2544 + */
2545 + function user_role_change( $user_id ) {
2546 + if ( Jetpack::is_active() && Jetpack::is_user_connected( $user_id ) ) {
2547 +
2548 + $current_user_id = get_current_user_id();
2549 + wp_set_current_user( $user_id );
2550 + $role = $this->translate_current_user_to_role();
2551 + $signed_role = $this->sign_role( $role );
2552 + wp_set_current_user( $current_user_id );
2553 +
2554 + $master_token = Jetpack_Data::get_access_token( JETPACK_MASTER_USER );
2555 + $master_user_id = absint( $master_token->external_user_id );
2556 +
2557 + if ( !$master_user_id )
2558 + return; // this shouldn't happen
2559 +
2560 + Jetpack::xmlrpc_async_call( 'jetpack.updateRole', $user_id, $signed_role );
2561 + //@todo retry on failure
2562 +
2563 + //try to choose a new master if we're demoting the current one
2564 + if ( $user_id == $master_user_id && 'administrator' != $role ) {
2565 + $query = new WP_User_Query( array(
2566 + 'fields' => array( 'id' ),
2567 + 'role' => 'administrator',
2568 + 'orderby' => 'id',
2569 + 'exclude' => array( $master_user_id ),
2570 + )
2571 + );
2572 + $new_master = false;
2573 + foreach ( $query->results as $result ) {
2574 + $uid = absint( $result->id );
2575 + if ( $uid && Jetpack::is_user_connected( $uid ) ) {
2576 + $new_master = $uid;
2577 + break;
2578 + }
2579 + }
2580 +
2581 + if ( $new_master ) {
2582 + Jetpack::update_option( 'master_user', $new_master );
2583 + }
2584 + // else disconnect..?
2585 + }
2586 + }
2587 + }
2588 +
2589 + /**
2590 + * Loads the currently active modules.
2591 + */
2592 + public static function load_modules() {
2593 +
2594 + /*
2595 + if ( ! Jetpack::is_active() && ! Jetpack::is_development_mode() ) {
2596 + return;
2597 + }
2598 + */
2599 +
2600 + $version = Jetpack::get_option( 'version' );
2601 + if ( !$version ) {
2602 + $version = $old_version = JETPACK__VERSION . ':' . time();
2603 + Jetpack::update_options( compact( 'version', 'old_version' ) );
2604 + }
2605 + list( $version ) = explode( ':', $version );
2606 +
2607 + $modules = array_filter( Jetpack::get_active_modules(), array( 'Jetpack', 'is_module' ) );
2608 +
2609 + $modules_data = array();
2610 +
2611 + // Don't load modules that have had "Major" changes since the stored version until they have been deactivated/reactivated through the lint check.
2612 + if ( version_compare( $version, JETPACK__VERSION, '<' ) ) {
2613 + $updated_modules = array();
2614 + foreach ( $modules as $module ) {
2615 + $modules_data[ $module ] = Jetpack::get_module( $module );
2616 + if ( ! isset( $modules_data[ $module ]['changed'] ) ) {
2617 + continue;
2618 + }
2619 +
2620 + if ( version_compare( $modules_data[ $module ]['changed'], $version, '<=' ) ) {
2621 + continue;
2622 + }
2623 +
2624 + $updated_modules[] = $module;
2625 + }
2626 +
2627 + $modules = array_diff( $modules, $updated_modules );
2628 + }
2629 +
2630 + foreach ( $modules as $module ) {
2631 + // If not connected and we're in dev mode, disable modules requiring a connection
2632 + if ( ! Jetpack::is_active() ) {
2633 + if ( empty( $modules_data[ $module ] ) ) {
2634 + $modules_data[ $module ] = Jetpack::get_module( $module );
2635 + }
2636 + if ( $modules_data[ $module ]['requires_connection'] || ! Jetpack::is_development_mode() ) {
2637 + continue;
2638 + }
2639 + }
2640 +
2641 + if ( did_action( 'jetpack_module_loaded_' . $module ) ) {
2642 + continue;
2643 + }
2644 +
2645 + require Jetpack::get_module_path( $module );
2646 + do_action( 'jetpack_module_loaded_' . $module );
2647 + }
2648 +
2649 + do_action( 'jetpack_modules_loaded' );
2650 +
2651 + // Load module-specific code that is needed even when a module isn't active. Loaded here because code contained therein may need actions such as setup_theme.
2652 + require_once( dirname( __FILE__ ) . '/modules/module-extras.php' );
2653 + }
2654 +
2655 + /**
2656 + * Check if Jetpack's REST API compat file should be included
2657 + * @action plugins_loaded
2658 + * @return null
2659 + */
2660 + public function check_rest_api_compat() {
2661 + $_jetpack_rest_api_compat_includes = apply_filters( 'jetpack_rest_api_compat', array() );
2662 +
2663 + if ( function_exists( 'bbpress' ) )
2664 + $_jetpack_rest_api_compat_includes[] = dirname( __FILE__ ) . '/class.jetpack-bbpress-json-api-compat.php';
2665 +
2666 + foreach ( $_jetpack_rest_api_compat_includes as $_jetpack_rest_api_compat_include )
2667 + require_once $_jetpack_rest_api_compat_include;
2668 + }
2669 +
2670 + /**
2671 + * Check if Jetpack's Open Graph tags should be used.
2672 + * If certain plugins are active, Jetpack's og tags are suppressed.
2673 + *
2674 + * @uses Jetpack::get_active_modules, add_filter, get_option, apply_filters
2675 + * @action plugins_loaded
2676 + * @return null
2677 + */
2678 + public function check_open_graph() {
2679 + if ( in_array( 'publicize', Jetpack::get_active_modules() ) || in_array( 'sharedaddy', Jetpack::get_active_modules() ) )
2680 + add_filter( 'jetpack_enable_open_graph', '__return_true', 0 );
2681 +
2682 + $active_plugins = get_option( 'active_plugins', array() );
2683 +
2684 + if ( is_multisite() ) {
2685 + // Due to legacy code, active_sitewide_plugins stores them in the keys,
2686 + // whereas active_plugins stores them in the values.
2687 + $network_plugins = array_keys( get_site_option( 'active_sitewide_plugins', array() ) );
2688 + if ( $network_plugins ) {
2689 + $active_plugins = array_merge( $active_plugins, $network_plugins );
2690 + }
2691 + }
2692 +
2693 + $conflicting_plugins = array(
2694 + 'facebook/facebook.php', // Official Facebook plugin
2695 + 'wordpress-seo/wp-seo.php', // WordPress SEO by Yoast
2696 + 'add-link-to-facebook/add-link-to-facebook.php', // Add Link to Facebook
2697 + 'facebook-awd/AWD_facebook.php', // Facebook AWD All in one
2698 + 'header-footer/plugin.php', // Header and Footer
2699 + 'nextgen-facebook/nextgen-facebook.php', // NextGEN Facebook OG
2700 + 'seo-facebook-comments/seofacebook.php', // SEO Facebook Comments
2701 + 'seo-ultimate/seo-ultimate.php', // SEO Ultimate
2702 + 'sexybookmarks/sexy-bookmarks.php', // Shareaholic
2703 + 'shareaholic/sexy-bookmarks.php', // Shareaholic
2704 + 'social-discussions/social-discussions.php', // Social Discussions
2705 + 'social-networks-auto-poster-facebook-twitter-g/NextScripts_SNAP.php', // NextScripts SNAP
2706 + 'wordbooker/wordbooker.php', // Wordbooker
2707 + 'socialize/socialize.php', // Socialize
2708 + 'simple-facebook-connect/sfc.php', // Simple Facebook Connect
2709 + 'social-sharing-toolkit/social_sharing_toolkit.php', // Social Sharing Toolkit
2710 + 'wp-facebook-open-graph-protocol/wp-facebook-ogp.php', // WP Facebook Open Graph protocol
2711 + 'opengraph/opengraph.php', // Open Graph
2712 + 'sharepress/sharepress.php', // SharePress
2713 + 'wp-facebook-like-send-open-graph-meta/wp-facebook-like-send-open-graph-meta.php', // WP Facebook Like Send & Open Graph Meta
2714 + 'network-publisher/networkpub.php', // Network Publisher
2715 + 'wp-ogp/wp-ogp.php', // WP-OGP
2716 + );
2717 +
2718 + foreach ( $conflicting_plugins as $plugin ) {
2719 + if ( in_array( $plugin, $active_plugins ) ) {
2720 + add_filter( 'jetpack_enable_open_graph', '__return_false', 99 );
2721 + break;
2722 + }
2723 + }
2724 +
2725 + if ( apply_filters( 'jetpack_enable_open_graph', false ) )
2726 + require_once dirname( __FILE__ ) . '/functions.opengraph.php';
2727 + }
2728 +
2729 +/* Jetpack Options API */
2730 +
2731 + public static function get_option_names( $type = 'compact' ) {
2732 + return Jetpack_Options::get_option_names( $type );
2733 + }
2734 +
2735 + /**
2736 + * Returns the requested option. Looks in jetpack_options or jetpack_$name as appropriate.
2737 + *
2738 + * @param string $name Option name
2739 + * @param mixed $default (optional)
2740 + */
2741 + public static function get_option( $name, $default = false ) {
2742 + return Jetpack_Options::get_option( $name, $default );
2743 + }
2744 +
2745 + /**
2746 + * Stores two secrets and a timestamp so WordPress.com can make a request back and verify an action
2747 + * Does some extra verification so urls (such as those to public-api, register, etc) cant just be crafted
2748 + * $name must be a registered option name.
2749 + */
2750 + public static function create_nonce( $name ) {
2751 + $secret = wp_generate_password( 32, false ) . ':' . wp_generate_password( 32, false ) . ':' . ( time() + 600 );
2752 +
2753 + Jetpack::update_option( $name, $secret );
2754 + @list( $secret_1, $secret_2, $eol ) = explode( ':', Jetpack::get_option( $name ) );
2755 + if ( empty( $secret_1 ) || empty( $secret_2 ) || $eol < time() )
2756 + return new Jetpack_Error( 'missing_secrets' );
2757 +
2758 + return array(
2759 + 'secret_1' => $secret_1,
2760 + 'secret_2' => $secret_2,
2761 + 'eol' => $eol,
2762 + );
2763 + }
2764 +
2765 + /**
2766 + * Updates the single given option. Updates jetpack_options or jetpack_$name as appropriate.
2767 + *
2768 + * @param string $name Option name
2769 + * @param mixed $value Option value
2770 + */
2771 + public static function update_option( $name, $value ) {
2772 + return Jetpack_Options::update_option( $name, $value );
2773 + }
2774 +
2775 + /**
2776 + * Updates the multiple given options. Updates jetpack_options and/or jetpack_$name as appropriate.
2777 + *
2778 + * @param array $array array( option name => option value, ... )
2779 + */
2780 + public static function update_options( $array ) {
2781 + return Jetpack_Options::update_options( $array );
2782 + }
2783 +
2784 + /**
2785 + * Deletes the given option. May be passed multiple option names as an array.
2786 + * Updates jetpack_options and/or deletes jetpack_$name as appropriate.
2787 + *
2788 + * @param string|array $names
2789 + */
2790 + public static function delete_option( $names ) {
2791 + return Jetpack_Options::delete_option( $names );
2792 + }
2793 +
2794 + /**
2795 + * Enters a user token into the user_tokens option
2796 + *
2797 + * @param int $user_id
2798 + * @param string $token
2799 + * return bool
2800 + */
2801 + public static function update_user_token( $user_id, $token, $is_master_user ) {
2802 + // not designed for concurrent updates
2803 + $user_tokens = Jetpack::get_option( 'user_tokens' );
2804 + if ( ! is_array( $user_tokens ) )
2805 + $user_tokens = array();
2806 + $user_tokens[$user_id] = $token;
2807 + if ( $is_master_user ) {
2808 + $master_user = $user_id;
2809 + $options = compact('user_tokens', 'master_user');
2810 + } else {
2811 + $options = compact('user_tokens');
2812 + }
2813 + return Jetpack::update_options( $options );
2814 + }
2815 +
2816 + /**
2817 + * Returns an array of all PHP files in the specified absolute path.
2818 + * Equivalent to glob( "$absolute_path/*.php" ).
2819 + *
2820 + * @param string $absolute_path The absolute path of the directory to search.
2821 + * @return array Array of absolute paths to the PHP files.
2822 + */
2823 + public static function glob_php( $absolute_path ) {
2824 + $absolute_path = untrailingslashit( $absolute_path );
2825 + $files = array();
2826 + if ( !$dir = @opendir( $absolute_path ) ) {
2827 + return $files;
2828 + }
2829 +
2830 + while ( false !== $file = readdir( $dir ) ) {
2831 + if ( '.' == substr( $file, 0, 1 ) || '.php' != substr( $file, -4 ) ) {
2832 + continue;
2833 + }
2834 +
2835 + $file = "$absolute_path/$file";
2836 +
2837 + if ( !is_file( $file ) ) {
2838 + continue;
2839 + }
2840 +
2841 + $files[] = $file;
2842 + }
2843 +
2844 + closedir( $dir );
2845 +
2846 + return $files;
2847 + }
2848 +
2849 + public function activate_new_modules() {
2850 + if ( ! Jetpack::is_active() && ! Jetpack::is_development_mode() ) {
2851 + return;
2852 + }
2853 +
2854 + $jetpack_old_version = Jetpack::get_option( 'version' ); // [sic]
2855 + if ( !$jetpack_old_version ) {
2856 + $jetpack_old_version = $version = $old_version = '1.1:' . time();
2857 + Jetpack::update_options( compact( 'version', 'old_version' ) );
2858 + }
2859 +
2860 + list( $jetpack_version ) = explode( ':', $jetpack_old_version ); // [sic]
2861 +
2862 + if ( version_compare( JETPACK__VERSION, $jetpack_version, '<=' ) ) {
2863 + return;
2864 + }
2865 +
2866 + $active_modules = Jetpack::get_active_modules();
2867 + $reactivate_modules = array();
2868 + foreach ( $active_modules as $active_module ) {
2869 + $module = Jetpack::get_module( $active_module );
2870 + if ( !isset( $module['changed'] ) ) {
2871 + continue;
2872 + }
2873 +
2874 + if ( version_compare( $module['changed'], $jetpack_version, '<=' ) ) {
2875 + continue;
2876 + }
2877 +
2878 + $reactivate_modules[] = $active_module;
2879 + Jetpack::deactivate_module( $active_module );
2880 + }
2881 +
2882 + if ( version_compare( $jetpack_version, '1.9.2', '<' ) && version_compare( '1.9-something', JETPACK__VERSION, '<' ) ) {
2883 + add_action( 'jetpack_activate_default_modules', array( $this->sync, 'sync_all_registered_options' ), 1000 );
2884 + }
2885 +
2886 + Jetpack::update_options( array(
2887 + 'version' => JETPACK__VERSION . ':' . time(),
2888 + 'old_version' => $jetpack_old_version,
2889 + ) );
2890 +
2891 + Jetpack::state( 'message', 'modules_activated' );
2892 + Jetpack::activate_default_modules( $jetpack_version, JETPACK__VERSION, $reactivate_modules );
2893 + wp_safe_redirect( Jetpack::admin_url( 'page=jetpack' ) );
2894 + exit;
2895 + }
2896 +
2897 + /**
2898 + * List available Jetpack modules. Simply lists .php files in /modules/.
2899 + * Make sure to tuck away module "library" files in a sub-directory.
2900 + */
2901 + public static function get_available_modules( $min_version = false, $max_version = false ) {
2902 + static $modules = null;
2903 +
2904 + if ( !isset( $modules ) ) {
2905 + $files = Jetpack::glob_php( dirname( __FILE__ ) . '/modules' );
2906 +
2907 + $modules = array();
2908 +
2909 + foreach ( $files as $file ) {
2910 + if ( !$headers = Jetpack::get_module( $file ) ) {
2911 + continue;
2912 + }
2913 +
2914 + $modules[ Jetpack::get_module_slug( $file ) ] = $headers['introduced'];
2915 + }
2916 + }
2917 +
2918 + if ( !$min_version && !$max_version ) {
2919 + return array_keys( $modules );
2920 + }
2921 +
2922 + $r = array();
2923 + foreach ( $modules as $slug => $introduced ) {
2924 + if ( $min_version && version_compare( $min_version, $introduced, '>=' ) ) {
2925 + continue;
2926 + }
2927 +
2928 + if ( $max_version && version_compare( $max_version, $introduced, '<' ) ) {
2929 + continue;
2930 + }
2931 +
2932 + $r[] = $slug;
2933 + }
2934 +
2935 + return $r;
2936 + }
2937 +
2938 + /**
2939 + * Default modules loaded on activation.
2940 + */
2941 + public static function get_default_modules( $min_version = false, $max_version = false ) {
2942 + $return = array();
2943 +
2944 + foreach ( Jetpack::get_available_modules( $min_version, $max_version ) as $module ) {
2945 + // Add special cases here for modules to avoid auto-activation
2946 + switch ( $module ) {
2947 +
2948 + // These modules are default off: they change things blog-side
2949 + case 'comments' :
2950 + case 'carousel' :
2951 + case 'minileven':
2952 + case 'infinite-scroll' :
2953 + case 'photon' :
2954 + case 'tiled-gallery' :
2955 + case 'likes' :
2956 + break;
2957 +
2958 + // These modules are default off if we think the site is a private one
2959 + case 'enhanced-distribution' :
2960 + case 'json-api' :
2961 + if ( !Jetpack::get_option( 'public' ) ) {
2962 + break;
2963 + }
2964 + // else no break
2965 + // The rest are default on
2966 + default :
2967 + $return[] = $module;
2968 + }
2969 + }
2970 +
2971 + return $return;
2972 + }
2973 +
2974 + /**
2975 + * Extract a module's slug from its full path.
2976 + */
2977 + public static function get_module_slug( $file ) {
2978 + return str_replace( '.php', '', basename( $file ) );
2979 + }
2980 +
2981 + /**
2982 + * Generate a module's path from its slug.
2983 + */
2984 + public static function get_module_path( $slug ) {
2985 + return dirname( __FILE__ ) . "/modules/$slug.php";
2986 + }
2987 +
2988 + /**
2989 + * Load module data from module file. Headers differ from WordPress
2990 + * plugin headers to avoid them being identified as standalone
2991 + * plugins on the WordPress plugins page.
2992 + */
2993 + public static function get_module( $module ) {
2994 + $headers = array(
2995 + 'name' => 'Module Name',
2996 + 'description' => 'Module Description',
2997 + 'sort' => 'Sort Order',
2998 + 'introduced' => 'First Introduced',
2999 + 'changed' => 'Major Changes In',
3000 + 'deactivate' => 'Deactivate',
3001 + 'free' => 'Free',
3002 + 'requires_connection' => 'Requires Connection',
3003 + );
3004 +
3005 + $file = Jetpack::get_module_path( Jetpack::get_module_slug( $module ) );
3006 + if ( !file_exists( $file ) )
3007 + return false;
3008 +
3009 + $mod = get_file_data( $file, $headers );
3010 + if ( empty( $mod['name'] ) )
3011 + return false;
3012 +
3013 + $mod['name'] = translate( $mod['name'], 'jetpack' );
3014 + $mod['description'] = translate( $mod['description'], 'jetpack' );
3015 + if ( empty( $mod['sort'] ) )
3016 + $mod['sort'] = 10;
3017 + $mod['deactivate'] = empty( $mod['deactivate'] );
3018 + $mod['free'] = empty( $mod['free'] );
3019 + $mod['requires_connection'] = ( ! empty( $mod['requires_connection'] ) && 'No' == $mod['requires_connection'] ) ? false : true;
3020 + return $mod;
3021 + }
3022 +
3023 + /**
3024 + * Get a list of activated modules as an array of module slugs.
3025 + */
3026 + public static function get_active_modules() {
3027 + $active = Jetpack::get_option( 'active_modules' );
3028 + if ( !is_array( $active ) )
3029 + $active = array();
3030 + if ( is_admin() ) {
3031 + $active[] = 'vaultpress';
3032 + } else {
3033 + $active = array_diff( $active, array( 'vaultpress' ) );
3034 + }
3035 + return array_unique( $active );
3036 + }
3037 +
3038 + /**
3039 + * Check whether or not a Jetpack module is active.
3040 + *
3041 + * @param string $module The slug of a Jetpack module.
3042 + * @return bool
3043 + *
3044 + * @static
3045 + */
3046 + public static function is_module_active( $module ) {
3047 + return in_array( $module, self::get_active_modules() );
3048 + }
3049 +
3050 + public static function is_module( $module ) {
3051 + return !empty( $module ) && !validate_file( $module, Jetpack::get_available_modules() );
3052 + }
3053 +
3054 + /**
3055 + * Catches PHP errors. Must be used in conjunction with output buffering.
3056 + *
3057 + * @param bool $catch True to start catching, False to stop.
3058 + *
3059 + * @static
3060 + */
3061 + public static function catch_errors( $catch ) {
3062 + static $display_errors, $error_reporting;
3063 +
3064 + if ( $catch ) {
3065 + $display_errors = @ini_set( 'display_errors', 1 );
3066 + $error_reporting = @error_reporting( E_ALL );
3067 + add_action( 'shutdown', array( 'Jetpack', 'catch_errors_on_shutdown' ), 0 );
3068 + } else {
3069 + @ini_set( 'display_errors', $display_errors );
3070 + @error_reporting( $error_reporting );
3071 + remove_action( 'shutdown', array( 'Jetpack', 'catch_errors_on_shutdown' ), 1 );
3072 + }
3073 + }
3074 +
3075 + /**
3076 + * Saves any generated PHP errors in ::state( 'php_errors', {errors} )
3077 + */
3078 + public static function catch_errors_on_shutdown() {
3079 + Jetpack::state( 'php_errors', ob_get_clean() );
3080 + }
3081 +
3082 + public static function activate_default_modules( $min_version = false, $max_version = false, $other_modules = array() ) {
3083 + $jetpack = Jetpack::init();
3084 +
3085 + $modules = Jetpack::get_default_modules( $min_version, $max_version );
3086 + $modules = array_merge( $other_modules, $modules );
3087 +
3088 + // Look for standalone plugins and disable if active.
3089 +
3090 + $to_deactivate = array();
3091 + foreach ( $modules as $module ) {
3092 + if ( isset( $jetpack->plugins_to_deactivate[$module] ) ) {
3093 + $to_deactivate[$module] = $jetpack->plugins_to_deactivate[$module];
3094 + }
3095 + }
3096 +
3097 + $deactivated = array();
3098 + foreach ( $to_deactivate as $module => $deactivate_me ) {
3099 + list( $probable_file, $probable_title ) = $deactivate_me;
3100 + if ( Jetpack_Client_Server::deactivate_plugin( $probable_file, $probable_title ) ) {
3101 + $deactivated[] = $module;
3102 + }
3103 + }
3104 +
3105 + if ( $deactivated ) {
3106 + Jetpack::state( 'deactivated_plugins', join( ',', $deactivated ) );
3107 +
3108 + $url = add_query_arg( array(
3109 + 'action' => 'activate_default_modules',
3110 + '_wpnonce' => wp_create_nonce( 'activate_default_modules' ),
3111 + ), add_query_arg( compact( 'min_version', 'max_version', 'other_modules' ), Jetpack::admin_url( 'page=jetpack' ) ) );
3112 + wp_safe_redirect( $url );
3113 + exit;
3114 + }
3115 +
3116 + do_action( 'jetpack_before_activate_default_modules', $min_version, $max_version, $other_modules );
3117 +
3118 + // Check each module for fatal errors, a la wp-admin/plugins.php::activate before activating
3119 + $redirect = menu_page_url( 'jetpack', false );
3120 + Jetpack::restate();
3121 + Jetpack::catch_errors( true );
3122 + foreach ( $modules as $module ) {
3123 + if ( did_action( "jetpack_module_loaded_$module" ) ) {
3124 + $active[] = $module;
3125 + Jetpack::update_option( 'active_modules', array_unique( $active ) );
3126 + continue;
3127 + }
3128 + $active = Jetpack::get_active_modules();
3129 + if ( in_array( $module, $active ) ) {
3130 + $module_info = Jetpack::get_module( $module );
3131 + if ( !$module_info['deactivate'] ) {
3132 + $state = in_array( $module, $other_modules ) ? 'reactivated_modules' : 'activated_modules';
3133 + if ( $active_state = Jetpack::state( $state ) ) {
3134 + $active_state = explode( ',', $active_state );
3135 + } else {
3136 + $active_state = array();
3137 + }
3138 + $active_state[] = $module;
3139 + Jetpack::state( $state, implode( ',', $active_state ) );
3140 + }
3141 + continue;
3142 + }
3143 +
3144 + $file = Jetpack::get_module_path( $module );
3145 + if ( !file_exists( $file ) ) {
3146 + continue;
3147 + }
3148 +
3149 + // we'll override this later if the plugin can be included without fatal error
3150 + wp_safe_redirect( Jetpack::admin_url( 'page=jetpack' ) );
3151 + Jetpack::state( 'error', 'module_activation_failed' );
3152 + Jetpack::state( 'module', $module );
3153 + ob_start();
3154 + require $file;
3155 + do_action( 'jetpack_activate_module', $module );
3156 + $active[] = $module;
3157 + $state = in_array( $module, $other_modules ) ? 'reactivated_modules' : 'activated_modules';
3158 + if ( $active_state = Jetpack::state( $state ) ) {
3159 + $active_state = explode( ',', $active_state );
3160 + } else {
3161 + $active_state = array();
3162 + }
3163 + $active_state[] = $module;
3164 + Jetpack::state( $state, implode( ',', $active_state ) );
3165 + Jetpack::update_option( 'active_modules', array_unique( $active ) );
3166 + ob_end_clean();
3167 + }
3168 + Jetpack::state( 'error', false );
3169 + Jetpack::state( 'module', false );
3170 + Jetpack::catch_errors( false );
3171 + do_action( 'jetpack_activate_default_modules', $min_version, $max_version, $other_modules );
3172 + }
3173 +
3174 + public static function activate_module( $module, $exit = true ) {
3175 + $jetpack = Jetpack::init();
3176 +
3177 + if ( ! strlen( $module ) )
3178 + return false;
3179 +
3180 + if ( ! Jetpack::is_module( $module ) )
3181 + return false;
3182 +
3183 + // If it's already active, then don't do it again
3184 + $active = Jetpack::get_active_modules();
3185 + foreach ( $active as $act ) {
3186 + if ( $act == $module )
3187 + return true;
3188 + }
3189 +
3190 + $module_data = Jetpack::get_module( $module );
3191 +
3192 + if ( ! Jetpack::is_active() ) {
3193 + if ( ! Jetpack::is_development_mode() )
3194 + return false;
3195 +
3196 + // If we're not connected but in development mode, make sure the module doesn't require a connection
3197 + if ( Jetpack::is_development_mode() && $module_data['requires_connection'] )
3198 + return false;
3199 + }
3200 +
3201 + // Check and see if the old plugin is active
3202 + if ( isset( $jetpack->plugins_to_deactivate[$module] ) ) {
3203 + // Deactivate the old plugin
3204 + if ( Jetpack_Client_Server::deactivate_plugin( $jetpack->plugins_to_deactivate[$module][0], $jetpack->plugins_to_deactivate[$module][1] ) ) {
3205 + // If we deactivated the old plugin, remembere that with ::state() and redirect back to this page to activate the module
3206 + // We can't activate the module on this page load since the newly deactivated old plugin is still loaded on this page load.
3207 + Jetpack::state( 'deactivated_plugins', $module );
3208 + wp_safe_redirect( add_query_arg( 'jetpack_restate', 1 ) );
3209 + exit;
3210 + }
3211 + }
3212 +
3213 + // Check the file for fatal errors, a la wp-admin/plugins.php::activate
3214 + Jetpack::state( 'module', $module );
3215 + Jetpack::state( 'error', 'module_activation_failed' ); // we'll override this later if the plugin can be included without fatal error
3216 + wp_safe_redirect( Jetpack::admin_url( 'page=jetpack' ) );
3217 +
3218 + Jetpack::catch_errors( true );
3219 + ob_start();
3220 + require Jetpack::get_module_path( $module );
3221 + do_action( 'jetpack_activate_module', $module );
3222 + $active[] = $module;
3223 + Jetpack::update_option( 'active_modules', array_unique( $active ) );
3224 + Jetpack::state( 'error', false ); // the override
3225 + Jetpack::state( 'message', 'module_activated' );
3226 + Jetpack::state( 'module', $module );
3227 + ob_end_clean();
3228 + Jetpack::catch_errors( false );
3229 +
3230 + if ( $exit ) {
3231 + exit;
3232 + }
3233 + }
3234 +
3235 + function activate_module_actions( $module ) {
3236 + do_action( "jetpack_activate_module_$module" );
3237 +
3238 + $this->sync->sync_all_module_options( $module );
3239 + }
3240 +
3241 + public static function deactivate_module( $module ) {
3242 + $active = Jetpack::get_active_modules();
3243 + $new = array();
3244 + foreach ( $active as $check ) {
3245 + if ( !empty( $check ) && $module != $check )
3246 + $new[] = $check;
3247 + }
3248 +
3249 + do_action( "jetpack_deactivate_module_$module" );
3250 + return Jetpack::update_option( 'active_modules', array_unique( $new ) );
3251 + }
3252 +
3253 + public static function enable_module_configurable( $module ) {
3254 + $module = Jetpack::get_module_slug( $module );
3255 + add_filter( 'jetpack_module_configurable_' . $module, '__return_true' );
3256 + }
3257 +
3258 + public static function module_configuration_url( $module ) {
3259 + $module = Jetpack::get_module_slug( $module );
3260 + return Jetpack::admin_url( array( 'page' => 'jetpack', 'configure' => $module ) );
3261 + }
3262 +
3263 + public static function module_configuration_load( $module, $method ) {
3264 + $module = Jetpack::get_module_slug( $module );
3265 + add_action( 'jetpack_module_configuration_load_' . $module, $method );
3266 + }
3267 +
3268 + public static function module_configuration_head( $module, $method ) {
3269 + $module = Jetpack::get_module_slug( $module );
3270 + add_action( 'jetpack_module_configuration_head_' . $module, $method );
3271 + }
3272 +
3273 + public static function module_configuration_screen( $module, $method ) {
3274 + $module = Jetpack::get_module_slug( $module );
3275 + add_action( 'jetpack_module_configuration_screen_' . $module, $method );
3276 + }
3277 +
3278 +/* Installation */
3279 +
3280 + public static function bail_on_activation( $message, $deactivate = true ) {
3281 +?>
3282 +<!doctype html>
3283 +<html>
3284 +<head>
3285 +<meta charset="<?php bloginfo( 'charset' ); ?>">
3286 +<style>
3287 +* {
3288 + text-align: center;
3289 + margin: 0;
3290 + padding: 0;
3291 + font-family: "Lucida Grande",Verdana,Arial,"Bitstream Vera Sans",sans-serif;
3292 +}
3293 +p {
3294 + margin-top: 1em;
3295 + font-size: 18px;
3296 +}
3297 +</style>
3298 +<body>
3299 +<p><?php echo esc_html( $message ); ?></p>
3300 +</body>
3301 +</html>
3302 +<?php
3303 + if ( $deactivate ) {
3304 + $plugins = get_option( 'active_plugins' );
3305 + $jetpack = plugin_basename( __FILE__ );
3306 + $update = false;
3307 + foreach ( $plugins as $i => $plugin ) {
3308 + if ( $plugin === $jetpack ) {
3309 + $plugins[$i] = false;
3310 + $update = true;
3311 + }
3312 + }
3313 +
3314 + if ( $update ) {
3315 + update_option( 'active_plugins', array_filter( $plugins ) );
3316 + }
3317 + }
3318 + exit;
3319 + }
3320 +
3321 + /**
3322 + * Attached to activate_{ plugin_basename( __FILES__ ) } by register_activation_hook()
3323 + * @static
3324 + */
3325 + public static function plugin_activation( $network_wide ) {
3326 + Jetpack::update_option( 'activated', 1 );
3327 +
3328 + if ( version_compare( $GLOBALS['wp_version'], JETPACK__MINIMUM_WP_VERSION, '<' ) ) {
3329 + Jetpack::bail_on_activation( sprintf( __( 'Jetpack requires WordPress version %s or later.', 'jetpack' ), JETPACK__MINIMUM_WP_VERSION ) );
3330 + }
3331 +
3332 + if ( $network_wide )
3333 + Jetpack::state( 'network_nag', true );
3334 +
3335 + Jetpack::plugin_initialize();
3336 + }
3337 +
3338 + /**
3339 + * Sets the internal version number and activation state.
3340 + * @static
3341 + */
3342 + public static function plugin_initialize() {
3343 + if ( !Jetpack::get_option( 'activated' ) ) {
3344 + Jetpack::update_option( 'activated', 2 );
3345 + }
3346 +
3347 + if ( !Jetpack::get_option( 'version' ) ) {
3348 + $version = $old_version = JETPACK__VERSION . ':' . time();
3349 + Jetpack::update_options( compact( 'version', 'old_version' ) );
3350 + }
3351 +
3352 + Jetpack::load_modules();
3353 +
3354 + Jetpack::delete_option( 'do_activate' );
3355 + }
3356 +
3357 + /**
3358 + * Removes all connection options
3359 + * @static
3360 + */
3361 + public static function plugin_deactivation( ) {
3362 + Jetpack::disconnect( false );
3363 +
3364 + Jetpack_Heartbeat::init()->deactivate();
3365 + }
3366 +
3367 + /**
3368 + * Disconnects from the Jetpack servers.
3369 + * Forgets all connection details and tells the Jetpack servers to do the same.
3370 + * @static
3371 + */
3372 + public static function disconnect( $update_activated_state = true ) {
3373 + wp_clear_scheduled_hook( 'jetpack_clean_nonces' );
3374 + Jetpack::clean_nonces( true );
3375 +
3376 + Jetpack::load_xml_rpc_client();
3377 + $xml = new Jetpack_IXR_Client();
3378 + $xml->query( 'jetpack.deregister' );
3379 +
3380 + Jetpack::delete_option( array(
3381 + 'register',
3382 + 'blog_token',
3383 + 'user_token',
3384 + 'user_tokens',
3385 + 'master_user',
3386 + 'time_diff',
3387 + 'fallback_no_verify_ssl_certs',
3388 + ) );
3389 +
3390 + if ( $update_activated_state ) {
3391 + Jetpack::update_option( 'activated', 4 );
3392 + }
3393 + }
3394 +
3395 + /**
3396 + * Unlinks the current user from the linked WordPress.com user
3397 + */
3398 + function unlink_user() {
3399 + if ( !$tokens = Jetpack::get_option( 'user_tokens' ) )
3400 + return false;
3401 +
3402 + $user_id = get_current_user_id();
3403 +
3404 + if ( Jetpack::get_option( 'master_user' ) == $user_id )
3405 + return false;
3406 +
3407 + if ( !isset( $tokens[$user_id] ) )
3408 + return false;
3409 +
3410 + Jetpack::load_xml_rpc_client();
3411 + $xml = new Jetpack_IXR_Client( compact( 'user_id' ) );
3412 + $xml->query( 'jetpack.unlink_user', $user_id );
3413 +
3414 + unset( $tokens[$user_id] );
3415 +
3416 + Jetpack::update_option( 'user_tokens', $tokens );
3417 +
3418 + return true;
3419 + }
3420 +
3421 + /**
3422 + * Attempts Jetpack registration. If it fail, a state flag is set: @see ::admin_page_load()
3423 + */
3424 + public static function try_registration() {
3425 + $result = Jetpack::register();
3426 +
3427 + // If there was an error with registration and the site was not registered, record this so we can show a message.
3428 + if ( !$result || is_wp_error( $result ) ) {
3429 + return $result;
3430 + } else {
3431 + return true;
3432 + }
3433 + }
3434 +
3435 +/* Admin Pages */
3436 +
3437 + function admin_init() {
3438 + // If the plugin is not connected, display a connect message.
3439 + if (
3440 + // the plugin was auto-activated and needs its candy
3441 + Jetpack::get_option( 'do_activate' )
3442 + ||
3443 + // the plugin is active, but was never activated. Probably came from a site-wide network activation
3444 + !Jetpack::get_option( 'activated' )
3445 + ) {
3446 + Jetpack::plugin_initialize();
3447 + }
3448 +
3449 + if ( !Jetpack::is_active() && ! Jetpack::is_development_mode() ) {
3450 + if ( 4 != Jetpack::get_option( 'activated' ) ) {
3451 + // Show connect notice on dashboard and plugins pages
3452 + add_action( 'load-index.php', array( $this, 'prepare_connect_notice' ) );
3453 + add_action( 'load-plugins.php', array( $this, 'prepare_connect_notice' ) );
3454 + }
3455 + } elseif ( false === Jetpack::get_option( 'fallback_no_verify_ssl_certs' ) ) {
3456 + // Upgrade: 1.1 -> 1.1.1
3457 + // Check and see if host can verify the Jetpack servers' SSL certificate
3458 + $args = array();
3459 + Jetpack_Client::_wp_remote_request(
3460 + Jetpack::fix_url_for_bad_hosts( Jetpack::api_url( 'test' ), $args ),
3461 + $args,
3462 + true
3463 + );
3464 + }
3465 +/* Toggle this off as it's not ready for prime time just yet.
3466 + if( current_user_can( 'manage_options' ) && self::check_identity_crisis() ) {
3467 + add_action( 'admin_notices', array( $this, 'alert_identity_crisis' ) );
3468 + }
3469 +/**/
3470 +
3471 + if ( current_user_can( 'manage_options' ) && 'ALWAYS' == JETPACK_CLIENT__HTTPS && ! self::permit_ssl() ) {
3472 + add_action( 'admin_notices', array( $this, 'alert_required_ssl_fail' ) );
3473 + }
3474 +
3475 + add_action( 'load-plugins.php', array( $this, 'intercept_plugin_error_scrape_init' ) );
3476 + add_action( 'admin_head', array( $this, 'admin_menu_css' ) );
3477 + add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'plugin_action_links' ) );
3478 +
3479 + if ( Jetpack::is_active() || Jetpack::is_development_mode() ) {
3480 + // Artificially throw errors in certain whitelisted cases during plugin activation
3481 + add_action( 'activate_plugin', array( $this, 'throw_error_on_activate_plugin' ) );
3482 +
3483 + // Kick off synchronization of user role when it changes
3484 + add_action( 'set_user_role', array( $this, 'user_role_change' ) );
3485 +
3486 + // Add retina images hotfix to admin
3487 + global $wp_db_version;
3488 + if ( ( $wp_db_version > 19470 ) && ( $wp_db_version < 22441 ) ) {
3489 + // WP 3.4.x
3490 + // DB Version 22441 = WP 3.5
3491 + add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_retina_scripts' ) );
3492 + // /wp-admin/customize.php omits the action above.
3493 + add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_retina_scripts' ) );
3494 + }
3495 + }
3496 + }
3497 +
3498 + function admin_body_class( $admin_body_class = '' ) {
3499 + if ( self::is_active() ) {
3500 + $admin_body_class .= ' jetpack-connected';
3501 + } else {
3502 + $admin_body_class .= ' jetpack-disconnected';
3503 + }
3504 + return $admin_body_class;
3505 + }
3506 +
3507 + function prepare_connect_notice() {
3508 + add_action( 'admin_print_styles', array( $this, 'admin_styles' ) );
3509 +
3510 + add_action( 'admin_notices', array( $this, 'admin_connect_notice' ) );
3511 +
3512 + if ( Jetpack::state( 'network_nag' ) )
3513 + add_action( 'network_admin_notices', array( $this, 'network_connect_notice' ) );
3514 + }
3515 +
3516 + /**
3517 + * Sometimes a plugin can activate without causing errors, but it will cause errors on the next page load.
3518 + * This function artificially throws errors for such cases (whitelisted).
3519 + *
3520 + * @param string $plugin The activated plugin.
3521 + */
3522 + function throw_error_on_activate_plugin( $plugin ) {
3523 + $active_modules = Jetpack::get_active_modules();
3524 +
3525 + // The Shortlinks module and the Stats plugin conflict, but won't cause errors on activation because of some function_exists() checks.
3526 + if ( function_exists( 'stats_get_api_key' ) && in_array( 'shortlinks', $active_modules ) ) {
3527 + $throw = false;
3528 +
3529 + // Try and make sure it really was the stats plugin
3530 + if ( !class_exists( 'ReflectionFunction' ) ) {
3531 + if ( 'stats.php' == basename( $plugin ) ) {
3532 + $throw = true;
3533 + }
3534 + } else {
3535 + $reflection = new ReflectionFunction( 'stats_get_api_key' );
3536 + if ( basename( $plugin ) == basename( $reflection->getFileName() ) ) {
3537 + $throw = true;
3538 + }
3539 + }
3540 +
3541 + if ( $throw ) {
3542 + trigger_error( sprintf( __( 'Jetpack contains the most recent version of the old &#8220;%1$s&#8221; plugin.', 'jetpack' ), 'WordPress.com Stats' ), E_USER_ERROR );
3543 + }
3544 + }
3545 + }
3546 +
3547 + function intercept_plugin_error_scrape_init() {
3548 + add_action( 'check_admin_referer', array( $this, 'intercept_plugin_error_scrape' ), 10, 2 );
3549 + }
3550 +
3551 + function intercept_plugin_error_scrape( $action, $result ) {
3552 + if ( !$result ) {
3553 + return;
3554 + }
3555 +
3556 + foreach ( $this->plugins_to_deactivate as $module => $deactivate_me ) {
3557 + if ( "plugin-activation-error_{$deactivate_me[0]}" == $action ) {
3558 + Jetpack::bail_on_activation( sprintf( __( 'Jetpack contains the most recent version of the old &#8220;%1$s&#8221; plugin.', 'jetpack' ), $deactivate_me[1] ), false );
3559 + }
3560 + }
3561 + }
3562 +
3563 + function admin_menu() {
3564 + list( $jetpack_version ) = explode( ':', Jetpack::get_option( 'version' ) );
3565 + if (
3566 + $jetpack_version
3567 + &&
3568 + $jetpack_version != JETPACK__VERSION
3569 + &&
3570 + ( $new_modules = Jetpack::get_default_modules( $jetpack_version, JETPACK__VERSION ) )
3571 + &&
3572 + is_array( $new_modules )
3573 + &&
3574 + ( $new_modules_count = count( $new_modules ) )
3575 + &&
3576 + ( Jetpack::is_active() || Jetpack::is_development_mode() )
3577 + ) {
3578 + $new_modules_count_i18n = number_format_i18n( $new_modules_count );
3579 + $span_title = esc_attr( sprintf( _n( 'One New Jetpack Module', '%s New Jetpack Modules', $new_modules_count, 'jetpack' ), $new_modules_count_i18n ) );
3580 + $title = sprintf( 'Jetpack %s', "<span class='update-plugins count-{$new_modules_count}' title='$span_title'><span class='update-count'>$new_modules_count_i18n</span></span>" );
3581 + } else {
3582 + $title = __( 'Jetpack', 'jetpack' );
3583 + }
3584 +
3585 + $hook = add_menu_page( 'Jetpack', $title, 'read', 'jetpack', array( $this, 'admin_page' ), 'div' );
3586 +
3587 + $debugger_hook = add_submenu_page( 'jetpack', 'Jetpack Debugging Center', '', 'manage_options', 'jetpack-debugger', array( $this, 'debugger_page' ) );
3588 + add_action( "admin_head-$debugger_hook", 'jetpack_debug_admin_head' );
3589 +
3590 +
3591 + add_action( "load-$hook", array( $this, 'admin_page_load' ) );
3592 +
3593 + if ( version_compare( $GLOBALS['wp_version'], '3.3', '<' ) ) {
3594 + if ( isset( $_GET['page'] ) && 'jetpack' == $_GET['page'] ) {
3595 + add_contextual_help( $hook, $this->jetpack_help() );
3596 + }
3597 + } else {
3598 + add_action( "load-$hook", array( $this, 'admin_help' ) );
3599 + }
3600 + add_action( "admin_head-$hook", array( $this, 'admin_head' ) );
3601 + add_filter( 'custom_menu_order', array( $this, 'admin_menu_order' ) );
3602 + add_filter( 'menu_order', array( $this, 'jetpack_menu_order' ) );
3603 +
3604 + add_action( "admin_print_styles-$hook", array( $this, 'admin_styles' ) );
3605 +
3606 + add_action( "admin_print_scripts-$hook", array( $this, 'admin_scripts' ) );
3607 +
3608 + do_action( 'jetpack_admin_menu' );
3609 + }
3610 +/*
3611 + function admin_menu_modules() {
3612 + $hook = add_submenu_page( 'jetpack', __( 'Jetpack Modules', 'jetpack' ), __( 'Modules', 'jetpack' ), 'edit_posts', 'jetpack_modules', array( $this, 'admin_page_modules' ) );
3613 +
3614 + add_action( "load-$hook", array( $this, 'admin_page_load' ) );
3615 + add_action( "load-$hook", array( $this, 'admin_help' ) );
3616 + add_action( "admin_head-$hook", array( $this, 'admin_head' ) );
3617 + add_action( "admin_print_styles-$hook", array( $this, 'admin_styles' ) );
3618 + add_action( "admin_print_scripts-$hook", array( $this, 'admin_scripts' ) );
3619 + }
3620 +/**/
3621 + function add_remote_request_handlers() {
3622 + add_action( 'wp_ajax_nopriv_jetpack_upload_file', array( $this, 'remote_request_handlers' ) );
3623 + }
3624 +
3625 + function remote_request_handlers() {
3626 + switch ( current_filter() ) {
3627 + case 'wp_ajax_nopriv_jetpack_upload_file' :
3628 + $response = $this->upload_handler();
3629 + break;
3630 + default :
3631 + $response = new Jetpack_Error( 'unknown_handler', 'Unknown Handler', 400 );
3632 + break;
3633 + }
3634 +
3635 + if ( !$response ) {
3636 + $response = new Jetpack_Error( 'unknown_error', 'Unknown Error', 400 );
3637 + }
3638 +
3639 + if ( is_wp_error( $response ) ) {
3640 + $status_code = $response->get_error_data();
3641 + $error = $response->get_error_code();
3642 + $error_description = $response->get_error_message();
3643 +
3644 + if ( !is_int( $status_code ) ) {
3645 + $status_code = 400;
3646 + }
3647 +
3648 + status_header( $status_code );
3649 + die( json_encode( (object) compact( 'error', 'error_description' ) ) );
3650 + }
3651 +
3652 + status_header( 200 );
3653 + if ( true === $response ) {
3654 + exit;
3655 + }
3656 +
3657 + die( json_encode( (object) $response ) );
3658 + }
3659 +
3660 + function upload_handler() {
3661 + if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) {
3662 + return new Jetpack_Error( 405, get_status_header_desc( 405 ), 405 );
3663 + }
3664 +
3665 + $user = wp_authenticate( '', '' );
3666 + if ( !$user || is_wp_error( $user ) ) {
3667 + return new Jetpack_Error( 403, get_status_header_desc( 403 ), 403 );
3668 + }
3669 +
3670 + wp_set_current_user( $user->ID );
3671 +
3672 + if ( !current_user_can( 'upload_files' ) ) {
3673 + return new Jetpack_Error( 'cannot_upload_files', 'User does not have permission to upload files', 403 );
3674 + }
3675 +
3676 + if ( empty( $_FILES ) ) {
3677 + return new Jetpack_Error( 'no_files_uploaded', 'No files were uploaded: nothing to process', 400 );
3678 + }
3679 +
3680 + foreach ( array_keys( $_FILES ) as $files_key ) {
3681 + if ( !isset( $_POST["_jetpack_file_hmac_{$files_key}"] ) ) {
3682 + return new Jetpack_Error( 'missing_hmac', 'An HMAC for one or more files is missing', 400 );
3683 + }
3684 + }
3685 +
3686 + $media_keys = array_keys( $_FILES['media'] );
3687 +
3688 + $token = Jetpack_Data::get_access_token( get_current_user_id() );
3689 + if ( !$token || is_wp_error( $token ) ) {
3690 + return new Jetpack_Error( 'unknown_token', 'Unknown Jetpack token', 403 );
3691 + }
3692 +
3693 + $uploaded_files = array();
3694 + $global_post = isset( $GLOBALS['post'] ) ? $GLOBALS['post'] : null;
3695 + unset( $GLOBALS['post'] );
3696 + foreach ( $_FILES['media']['name'] as $index => $name ) {
3697 + $file = array();
3698 + foreach ( $media_keys as $media_key ) {
3699 + $file[$media_key] = $_FILES['media'][$media_key][$index];
3700 + }
3701 +
3702 + list( $hmac_provided, $salt ) = explode( ':', $_POST['_jetpack_file_hmac_media'][$index] );
3703 +
3704 + $hmac_file = hash_hmac_file( 'sha1', $file['tmp_name'], $salt . $token->secret );
3705 + if ( $hmac_provided !== $hmac_file ) {
3706 + $uploaded_files[$index] = (object) array( 'error' => 'invalid_hmac', 'error_description' => 'The corresponding HMAC for this file does not match' );
3707 + continue;
3708 + }
3709 +
3710 + $_FILES['.jetpack.upload.'] = $file;
3711 + $post_id = isset( $_POST['post_id'][$index] ) ? absint( $_POST['post_id'][$index] ) : 0;
3712 + if ( !current_user_can( 'edit_post', $post_id ) ) {
3713 + $post_id = 0;
3714 + }
3715 + $attachment_id = media_handle_upload( '.jetpack.upload.', $post_id, array(), array(
3716 + 'action' => 'jetpack_upload_file',
3717 + ) );
3718 +
3719 + if ( !$attachment_id ) {
3720 + $uploaded_files[$index] = (object) array( 'error' => 'unknown', 'error_description' => 'An unknown problem occurred processing the upload on the Jetpack site' );
3721 + } elseif ( is_wp_error( $attachment_id ) ) {
3722 + $uploaded_files[$index] = (object) array( 'error' => 'attachment_' . $attachment_id->get_error_code(), 'error_description' => $attachment_id->get_error_message() );
3723 + } else {
3724 + $attachment = get_post( $attachment_id );
3725 + $uploaded_files[$index] = (object) array(
3726 + 'id' => (string) $attachment_id,
3727 + 'file' => $attachment->post_title,
3728 + 'url' => wp_get_attachment_url( $attachment_id ),
3729 + 'type' => $attachment->post_mime_type,
3730 + 'meta' => wp_get_attachment_metadata( $attachment_id ),
3731 + );
3732 + }
3733 + }
3734 + if ( !is_null( $global_post ) ) {
3735 + $GLOBALS['post'] = $global_post;
3736 + }
3737 +
3738 + return $uploaded_files;
3739 + }
3740 +
3741 + /**
3742 + * Add help to the Jetpack page
3743 + *
3744 + * Deprecated. Remove when Jetpack requires WP 3.3+
3745 + */
3746 + function jetpack_help() {
3747 + return
3748 + '<p><strong>' . __( 'Jetpack by WordPress.com', 'jetpack' ) . '</strong></p>' .
3749 + '<p>' . __( 'Jetpack supercharges your self-hosted WordPress site with the awesome cloud power of WordPress.com.', 'jetpack' ) . '</p>' .
3750 + '<p>' . __( 'On this page, you are able to view the modules available within Jetpack, learn more about them, and activate or deactivate them as needed.', 'jetpack' ) . '</p>' .
3751 + '<p><strong>' . __( 'Jetpack Module Options', 'jetpack' ) . '</strong></p>' .
3752 + '<p>' . __( '<strong>To Activate/Deactivate a Module</strong> - Click on Learn More. An Activate or Deactivate button will now appear next to the Learn More button. Click the Activate/Deactivate button.', 'jetpack' ) . '</p>' .
3753 + '<p><strong>' . __( 'For more information:', 'jetpack' ) . '</strong></p>' .
3754 + '<p><a href="http://jetpack.me/faq/" target="_blank">' . __( 'Jetpack FAQ', 'jetpack' ) . '</a></p>' .
3755 + '<p><a href="http://jetpack.me/support/" target="_blank">' . __( 'Jetpack Support', 'jetpack' ) . '</a></p>';
3756 + }
3757 +
3758 + /**
3759 + * Add help to the Jetpack page
3760 + *
3761 + * @since Jetpack (1.2.3)
3762 + * @return false if not the Jetpack page
3763 + */
3764 + function admin_help() {
3765 + $current_screen = get_current_screen();
3766 +
3767 + // Overview
3768 + $current_screen->add_help_tab( array(
3769 + 'id' => 'overview',
3770 + 'title' => __( 'Overview', 'jetpack' ),
3771 + 'content' =>
3772 + '<p><strong>' . __( 'Jetpack by WordPress.com', 'jetpack' ) . '</strong></p>' .
3773 + '<p>' . __( 'Jetpack supercharges your self-hosted WordPress site with the awesome cloud power of WordPress.com.', 'jetpack' ) . '</p>' .
3774 + '<p>' . __( 'On this page, you are able to view the modules available within Jetpack, learn more about them, and activate or deactivate them as needed.', 'jetpack' ) . '</p>'
3775 + ) );
3776 +
3777 + // Screen Content
3778 + if ( current_user_can( 'manage_options' ) ) {
3779 + $current_screen->add_help_tab( array(
3780 + 'id' => 'modules',
3781 + 'title' => __( 'Modules', 'jetpack' ),
3782 + 'content' =>
3783 + '<p><strong>' . __( 'Jetpack by WordPress.com', 'jetpack' ) . '</strong></p>' .
3784 + '<p>' . __( 'You can activate or deactivate individual Jetpack modules to suit your needs.', 'jetpack' ) . '</p>' .
3785 + '<ol>' .
3786 + '<li>' . __( 'Find the component you want to manage', 'jetpack' ) . '</li>' .
3787 + '<li>' . __( 'Click on Learn More', 'jetpack' ) . '</li>' .
3788 + '<li>' . __( 'An Activate or Deactivate button will appear', 'jetpack' ) . '</li>' .
3789 + '<li>' . __( 'If additional settings are available, a link to them will appear', 'jetpack' ) . '</li>' .
3790 + '</ol>'
3791 + ) );
3792 + }
3793 +
3794 + // Help Sidebar
3795 + $current_screen->set_help_sidebar(
3796 + '<p><strong>' . __( 'For more information:', 'jetpack' ) . '</strong></p>' .
3797 + '<p><a href="http://jetpack.me/faq/" target="_blank">' . __( 'Jetpack FAQ', 'jetpack' ) . '</a></p>' .
3798 + '<p><a href="http://jetpack.me/support/" target="_blank">' . __( 'Jetpack Support', 'jetpack' ) . '</a></p>' .
3799 + '<p><a href="' . Jetpack::admin_url( array( 'page' => 'jetpack-debugger' ) ) .'">' . __( 'Jetpack Debugging Center', 'jetpack' ) . '</a></p>'
3800 +
3801 + );
3802 + }
3803 +
3804 + function admin_menu_css() { ?>
3805 + <style type="text/css" id="jetpack-menu-css">
3806 + #toplevel_page_jetpack .wp-menu-image {
3807 + background: url( <?php echo plugins_url( basename( dirname( __FILE__ ) ) . '/_inc/images/menuicon-sprite.png' ) ?> ) 0 90% no-repeat;
3808 + }
3809 + /* Retina Jetpack Menu Icon */
3810 + @media only screen and (-moz-min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3/2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) {
3811 + #toplevel_page_jetpack .wp-menu-image {
3812 + background: url( <?php echo plugins_url( basename( dirname( __FILE__ ) ) . '/_inc/images/menuicon-sprite-2x.png' ) ?> ) 0 90% no-repeat;
3813 + background-size:30px 64px;
3814 + }
3815 + }
3816 + #toplevel_page_jetpack.current .wp-menu-image,
3817 + #toplevel_page_jetpack.wp-has-current-submenu .wp-menu-image,
3818 + #toplevel_page_jetpack:hover .wp-menu-image {
3819 + background-position: top left;
3820 + }
3821 + </style><?php
3822 + }
3823 +
3824 + function admin_menu_order() {
3825 + return true;
3826 + }
3827 +
3828 + function jetpack_menu_order( $menu_order ) {
3829 + $jp_menu_order = array();
3830 +
3831 + foreach ( $menu_order as $index => $item ) {
3832 + if ( $item != 'jetpack' )
3833 + $jp_menu_order[] = $item;
3834 +
3835 + if ( $index == 0 )
3836 + $jp_menu_order[] = 'jetpack';
3837 + }
3838 +
3839 + return $jp_menu_order;
3840 + }
3841 +
3842 + function admin_head() {
3843 + if ( isset( $_GET['configure'] ) && Jetpack::is_module( $_GET['configure'] ) && current_user_can( 'manage_options' ) )
3844 + do_action( 'jetpack_module_configuration_head_' . $_GET['configure'] );
3845 + }
3846 +
3847 + function admin_styles() {
3848 + global $wp_styles;
3849 + wp_enqueue_style( 'jetpack', plugins_url( basename( dirname( __FILE__ ) ) . '/_inc/jetpack.css' ), false, JETPACK__VERSION . '-20121016' );
3850 + $wp_styles->add_data( 'jetpack', 'rtl', true );
3851 + }
3852 +
3853 + function admin_scripts() {
3854 + wp_enqueue_script( 'jetpack-js', plugins_url( basename( dirname( __FILE__ ) ) ) . '/_inc/jetpack.js', array( 'jquery' ), JETPACK__VERSION . '-20121111' );
3855 + wp_localize_script( 'jetpack-js', 'jetpackL10n', array(
3856 + 'ays_disconnect' => "This will deactivate all Jetpack modules.\nAre you sure you want to disconnect?",
3857 + 'ays_unlink' => "This will prevent user-specific modules such as Publicize, Notifications and Post By Email from working.\nAre you sure you want to unlink?",
3858 + 'ays_dismiss' => "This will deactivate Jetpack.\nAre you sure you want to deactivate Jetpack?",
3859 + ) );
3860 + add_action( 'admin_footer', array( $this, 'do_stats' ) );
3861 + }
3862 +
3863 + function enqueue_retina_scripts() {
3864 + wp_enqueue_style( 'jetpack-retina', plugins_url( basename( dirname( __FILE__ ) ) . '/_inc/jetpack-retina.css' ), false, JETPACK__VERSION . '-20120730' );
3865 + }
3866 +
3867 + function plugin_action_links( $actions ) {
3868 + return array_merge(
3869 + array( 'settings' => sprintf( '<a href="%s">%s</a>', Jetpack::admin_url(), __( 'Settings', 'jetpack' ) ) ),
3870 + $actions
3871 + );
3872 + return $actions;
3873 + }
3874 +
3875 + function admin_connect_notice() {
3876 + // Don't show the connect notice on the jetpack settings page. @todo: must be a better way?
3877 + if ( false !== strpos( $_SERVER['QUERY_STRING'], 'page=jetpack' ) )
3878 + return;
3879 +
3880 + if ( !current_user_can( 'manage_options' ) )
3881 + return;
3882 + ?>
3883 +
3884 + <div id="message" class="updated jetpack-message jp-connect">
3885 + <div id="jp-dismiss" class="jetpack-close-button-container">
3886 + <a class="jetpack-close-button" href="?page=jetpack&jetpack-notice=dismiss" title="<?php _e( 'Dismiss this notice and deactivate Jetpack.', 'jetpack' ); ?>"><?php _e( 'Dismiss this notice and deactivate Jetpack.', 'jetpack' ); ?></a>
3887 + </div>
3888 + <div class="jetpack-wrap-container">
3889 + <div class="jetpack-text-container">
3890 + <h4>
3891 + <?php if ( 1 == Jetpack::get_option( 'activated' ) ) : ?>
3892 + <p><?php _e( '<strong>Your Jetpack is almost ready</strong> &#8211; A connection to WordPress.com is needed to enable features like Stats, Contact Forms, and Subscriptions. Connect now to get fueled up!', 'jetpack' ); ?></p>
3893 + <?php else : ?>
3894 + <p><?php _e( '<strong>Jetpack is installed</strong> and ready to bring awesome, WordPress.com cloud-powered features to your site.', 'jetpack' ) ?></p>
3895 + <?php endif; ?>
3896 + </h4>
3897 + </div>
3898 + <div class="jetpack-install-container">
3899 + <?php if ( 1 == Jetpack::get_option( 'activated' ) ) : ?>
3900 + <p class="submit"><a href="<?php echo $this->build_connect_url() ?>" class="button-connector" id="wpcom-connect"><?php _e( 'Connect to WordPress.com', 'jetpack' ); ?></a></p>
3901 + <?php else : ?>
3902 + <p class="submit"><a href="<?php echo Jetpack::admin_url() ?>" class="button-connector" id="wpcom-connect"><?php _e( 'Learn More', 'jetpack' ); ?></a></p>
3903 + <?php endif; ?>
3904 + </div>
3905 + </div>
3906 + </div>
3907 +
3908 + <?php
3909 + }
3910 +
3911 + function network_connect_notice() {
3912 + ?>
3913 + <div id="message" class="updated jetpack-message">
3914 + <div class="squeezer">
3915 + <h4><?php _e( '<strong>Jetpack is activated!</strong> Each site on your network must be connected individually by an admin on that site.', 'jetpack' ) ?></h4>
3916 + </div>
3917 + </div>
3918 + <?php
3919 + }
3920 +
3921 + public static function jetpack_comment_notice() {
3922 + if ( in_array( 'comments', Jetpack::get_active_modules() ) ) {
3923 + return '';
3924 + }
3925 +
3926 + $jetpack_old_version = explode( ':', Jetpack::get_option( 'old_version' ) );
3927 + $jetpack_new_version = explode( ':', Jetpack::get_option( 'version' ) );
3928 +
3929 + if ( $jetpack_old_version ) {
3930 + if ( version_compare( $jetpack_old_version[0], '1.4', '>=' ) ) {
3931 + return '';
3932 + }
3933 + }
3934 +
3935 + if ( $jetpack_new_version ) {
3936 + if ( version_compare( $jetpack_new_version[0], '1.4-something', '<' ) ) {
3937 + return '';
3938 + }
3939 + }
3940 +
3941 + return '<br /><br />' . sprintf(
3942 + __( 'Jetpack now includes Jetpack Comments, which enables your visitors to use their WordPress.com, Twitter, or Facebook accounts when commenting on your site. To activate Jetpack Comments, <a href="%s">%s</a>.', 'jetpack' ),
3943 + wp_nonce_url(
3944 + Jetpack::admin_url( array(
3945 + 'page' => 'jetpack',
3946 + 'action' => 'activate',
3947 + 'module' => 'comments',
3948 + ) ),
3949 + "jetpack_activate-comments"
3950 + ),
3951 + __( 'click here', 'jetpack' )
3952 + );
3953 + }
3954 +
3955 + /*
3956 + * Registration flow:
3957 + * 1 - ::admin_page_load() action=register
3958 + * 2 - ::try_registration()
3959 + * 3 - ::register()
3960 + * - Creates jetpack_register option containing two secrets and a timestamp
3961 + * - Calls https://jetpack.wordpress.com/jetpack.register/1/ with
3962 + * siteurl, home, gmt_offset, timezone_string, site_name, secret_1, secret_2, site_lang, timeout, stats_id
3963 + * - That request to jetpack.wordpress.com does not immediately respond. It first makes a request BACK to this site's
3964 + * xmlrpc.php?for=jetpack: RPC method: jetpack.verifyRegistration, Parameters: secret_1
3965 + * - The XML-RPC request verifies secret_1, deletes both secrets and responds with: secret_2
3966 + * - https://jetpack.wordpress.com/jetpack.register/1/ verifies that XML-RPC response (secret_2) then finally responds itself with
3967 + * jetpack_id, jetpack_secret, jetpack_public
3968 + * - ::register() then stores jetpack_options: id => jetpack_id, blog_token => jetpack_secret
3969 + * 4 - redirect to https://jetpack.wordpress.com/jetpack.authorize/1/
3970 + * 5 - user logs in with WP.com account
3971 + * 6 - redirect to this site's wp-admin/index.php?page=jetpack&action=authorize with
3972 + * code <-- OAuth2 style authorization code
3973 + * 7 - ::admin_page_load() action=authorize
3974 + * 8 - Jetpack_Client_Server::authorize()
3975 + * 9 - Jetpack_Client_Server::get_token()
3976 + * 10- GET https://jetpack.wordpress.com/jetpack.token/1/ with
3977 + * client_id, client_secret, grant_type, code, redirect_uri:action=authorize, state, scope, user_email, user_login
3978 + * 11- which responds with
3979 + * access_token, token_type, scope
3980 + * 12- Jetpack_Client_Server::authorize() stores jetpack_options: user_token => access_token.$user_id
3981 + * 13- Jetpack::activate_default_modules()
3982 + * Deactivates deprecated plugins
3983 + * Activates all default modules
3984 + * Catches errors: redirects to wp-admin/index.php?page=jetpack state:error=something
3985 + * 14- redirect to this site's wp-admin/index.php?page=jetpack with state:message=authorized
3986 + * Done!
3987 + */
3988 +
3989 + /**
3990 + * Handles the page load events for the Jetpack admin page
3991 + */
3992 + function admin_page_load() {
3993 + $error = false;
3994 +
3995 + if ( !empty( $_GET['jetpack_restate'] ) ) {
3996 + // Should only be used in intermediate redirects to preserve state across redirects
3997 + Jetpack::restate();
3998 + }
3999 +
4000 + if ( isset( $_GET['connect_url_redirect'] ) ) {
4001 + // User clicked in the iframe to link their accounts
4002 + if ( ! Jetpack::is_user_connected() ) {
4003 + $connect_url = $this->build_connect_url( true );
4004 + if ( isset( $_GET['notes_iframe'] ) )
4005 + $connect_url .= '&notes_iframe';
4006 + wp_redirect( $connect_url );
4007 + exit;
4008 + } else {
4009 + Jetpack::state( 'message', 'already_authorized' );
4010 + wp_safe_redirect( Jetpack::admin_url() );
4011 + exit;
4012 + }
4013 + }
4014 +
4015 + if ( isset( $_GET['action'] ) ) {
4016 + switch ( $_GET['action'] ) {
4017 + case 'authorize' :
4018 + if ( Jetpack::is_active() && Jetpack::is_user_connected() ) {
4019 + Jetpack::state( 'message', 'already_authorized' );
4020 + wp_safe_redirect( Jetpack::admin_url() );
4021 + exit;
4022 + }
4023 + $client_server = new Jetpack_Client_Server;
4024 + $client_server->authorize();
4025 + exit;
4026 + case 'register' :
4027 + check_admin_referer( 'jetpack-register' );
4028 + $registered = Jetpack::try_registration();
4029 + if ( is_wp_error( $registered ) ) {
4030 + $error = $registered->get_error_code();
4031 + Jetpack::state( 'error_description', $registered->get_error_message() );
4032 + break;
4033 + }
4034 +
4035 + wp_redirect( $this->build_connect_url( true ) );
4036 + exit;
4037 + case 'activate' :
4038 + if ( ! current_user_can( 'activate_plugins' ) ) {
4039 + $error = 'cheatin';
4040 + break;
4041 + }
4042 +
4043 + $module = stripslashes( $_GET['module'] );
4044 + check_admin_referer( "jetpack_activate-$module" );
4045 + Jetpack::activate_module( $module );
4046 + // The following two lines will rarely happen, as Jetpack::activate_module normally exits at the end.
4047 + wp_safe_redirect( Jetpack::admin_url( 'page=jetpack' ) );
4048 + exit;
4049 + case 'activate_default_modules' :
4050 + check_admin_referer( 'activate_default_modules' );
4051 + Jetpack::restate();
4052 + $min_version = isset( $_GET['min_version'] ) ? $_GET['min_version'] : false;
4053 + $max_version = isset( $_GET['max_version'] ) ? $_GET['max_version'] : false;
4054 + $other_modules = isset( $_GET['other_modules'] ) && is_array( $_GET['other_modules'] ) ? $_GET['other_modules'] : array();
4055 + Jetpack::activate_default_modules( $min_version, $max_version, $other_modules );
4056 + wp_safe_redirect( Jetpack::admin_url( 'page=jetpack' ) );
4057 + exit;
4058 + case 'disconnect' :
4059 + check_admin_referer( 'jetpack-disconnect' );
4060 + Jetpack::disconnect();
4061 + wp_safe_redirect( Jetpack::admin_url() );
4062 + exit;
4063 + case 'reconnect' :
4064 + if ( ! current_user_can( 'manage_options' ) ) {
4065 + $error = 'cheatin';
4066 + break;
4067 + }
4068 +
4069 + check_admin_referer( 'jetpack-reconnect' );
4070 + $this->disconnect();
4071 + wp_redirect( $this->build_connect_url( true ) );
4072 + exit;
4073 + case 'deactivate' :
4074 + if ( ! current_user_can( 'activate_plugins' ) ) {
4075 + $error = 'cheatin';
4076 + break;
4077 + }
4078 +
4079 + $modules = stripslashes( $_GET['module'] );
4080 + check_admin_referer( "jetpack_deactivate-$modules" );
4081 + foreach ( explode( ',', $modules ) as $module ) {
4082 + Jetpack::deactivate_module( $module );
4083 + Jetpack::state( 'message', 'module_deactivated' );
4084 + }
4085 + Jetpack::state( 'module', $modules );
4086 + wp_safe_redirect( Jetpack::admin_url( 'page=jetpack' ) );
4087 + exit;
4088 + case 'unlink' :
4089 + check_admin_referer( 'jetpack-unlink' );
4090 + $this->unlink_user();
4091 + Jetpack::state( 'message', 'unlinked' );
4092 + wp_safe_redirect( Jetpack::admin_url() );
4093 + exit;
4094 + }
4095 + }
4096 +
4097 + if ( !$error = $error ? $error : Jetpack::state( 'error' ) ) {
4098 + $this->activate_new_modules();
4099 + }
4100 +
4101 + switch ( $error ) {
4102 + case 'cheatin' :
4103 + $this->error = __( 'Cheatin&#8217; uh?', 'jetpack' );
4104 + break;
4105 + case 'access_denied' :
4106 + $this->error = __( 'You need to authorize the Jetpack connection between your site and WordPress.com to enable the awesome features.', 'jetpack' );
4107 + break;
4108 + case 'wrong_state' :
4109 + $this->error = __( "Don&#8217;t cross the streams! You need to stay logged in to your WordPress blog while you authorize Jetpack.", 'jetpack' );
4110 + break;
4111 + case 'invalid_client' :
4112 + // @todo re-register instead of deactivate/reactivate
4113 + $this->error = __( 'Return to sender. Whoops! It looks like you got the wrong Jetpack in the mail; deactivate then reactivate the Jetpack plugin to get a new one.', 'jetpack' );
4114 + break;
4115 + case 'invalid_grant' :
4116 + $this->error = __( "Wrong size. Hm&#8230; it seems your Jetpack doesn&#8217;t quite fit. Have you lost weight? Click &#8220;Connect to WordPress.com&#8221; again to get your Jetpack adjusted.", 'jetpack' );
4117 + break;
4118 + case 'site_inaccessible' :
4119 + case 'site_requires_authorization' :
4120 + $this->error = sprintf( __( 'Your website needs to be publicly accessible to use Jetpack: %s', 'jetpack' ), "<code>$error</code>" );
4121 + break;
4122 + case 'module_activation_failed' :
4123 + $module = Jetpack::state( 'module' );
4124 + if ( !empty( $module ) && $mod = Jetpack::get_module( $module ) ) {
4125 + $this->error = sprintf( __( '%s could not be activated because it triggered a <strong>fatal error</strong>. Perhaps there is a conflict with another plugin you have installed?', 'jetpack' ), $mod['name'] );
4126 + if ( isset( $this->plugins_to_deactivate[$module] ) ) {
4127 + $this->error .= ' ' . sprintf( __( 'Do you still have the %s plugin installed?', 'jetpack' ), $this->plugins_to_deactivate[$module][1] );
4128 + }
4129 + } else {
4130 + $this->error = __( 'Module could not be activated because it triggered a <strong>fatal error</strong>. Perhaps there is a conflict with another plugin you have installed?', 'jetpack' );
4131 + }
4132 + if ( $php_errors = Jetpack::state( 'php_errors' ) ) {
4133 + $this->error .= "<br />\n";
4134 + $this->error .= $php_errors;
4135 + }
4136 + break;
4137 + case 'not_public' :
4138 + $this->error = __( "<strong>Your Jetpack has a glitch.</strong> Connecting this site with WordPress.com is not possible. This usually means your site is not publicly accessible (localhost).", 'jetpack' );
4139 + break;
4140 + case 'wpcom_408' :
4141 + case 'wpcom_5??' :
4142 + case 'wpcom_bad_response' :
4143 + case 'wpcom_outage' :
4144 + $this->error = __( 'WordPress.com is currently having problems and is unable to fuel up your Jetpack. Please try again later.', 'jetpack' );
4145 + break;
4146 + case 'register_http_request_failed' :
4147 + case 'token_http_request_failed' :
4148 + $this->error = sprintf( __( 'Jetpack could not contact WordPress.com: %s. This usually means something is incorrectly configured on your web host.', 'jetpack' ), "<code>$error</code>" );
4149 + break;
4150 + default :
4151 + if ( empty( $error ) ) {
4152 + break;
4153 + }
4154 + $error = trim( substr( strip_tags( $error ), 0, 20 ) );
4155 + // no break: fall through
4156 + case 'no_role' :
4157 + case 'no_cap' :
4158 + case 'no_code' :
4159 + case 'no_state' :
4160 + case 'invalid_state' :
4161 + case 'invalid_request' :
4162 + case 'invalid_scope' :
4163 + case 'unsupported_response_type' :
4164 + case 'invalid_token' :
4165 + case 'no_token' :
4166 + case 'missing_secrets' :
4167 + case 'home_missing' :
4168 + case 'siteurl_missing' :
4169 + case 'gmt_offset_missing' :
4170 + case 'site_name_missing' :
4171 + case 'secret_1_missing' :
4172 + case 'secret_2_missing' :
4173 + case 'site_lang_missing' :
4174 + case 'home_malformed' :
4175 + case 'siteurl_malformed' :
4176 + case 'gmt_offset_malformed' :
4177 + case 'timezone_string_malformed' :
4178 + case 'site_name_malformed' :
4179 + case 'secret_1_malformed' :
4180 + case 'secret_2_malformed' :
4181 + case 'site_lang_malformed' :
4182 + case 'secrets_mismatch' :
4183 + case 'verify_secret_1_missing' :
4184 + case 'verify_secret_1_malformed' :
4185 + case 'verify_secrets_missing' :
4186 + case 'verify_secrets_mismatch' :
4187 + $error = esc_html( $error );
4188 + $this->error = sprintf( __( "<strong>Your Jetpack has a glitch.</strong> Something went wrong that&#8217;s never supposed to happen. Guess you&#8217;re just lucky: %s", 'jetpack' ), "<code>$error</code>" );
4189 + if ( !Jetpack::is_active() ) {
4190 + $this->error .= '<br />';
4191 + $this->error .= sprintf( __( 'Try connecting again.', 'jetpack' ) );
4192 + }
4193 + break;
4194 + }
4195 +
4196 + $message_code = Jetpack::state( 'message' );
4197 +
4198 + $active_state = Jetpack::state( 'activated_modules' );
4199 + if ( !empty( $active_state ) ) {
4200 + $available = Jetpack::get_available_modules();
4201 + $active_state = explode( ',', $active_state );
4202 + $active_state = array_intersect( $active_state, $available );
4203 + if ( count( $active_state ) ) {
4204 + foreach ( $active_state as $mod ) {
4205 + $this->stat( 'module-activated', $mod );
4206 + }
4207 + } else {
4208 + $active_state = false;
4209 + }
4210 + }
4211 +
4212 + switch ( $message_code ) {
4213 + case 'modules_activated' :
4214 + $this->message = sprintf(
4215 + __( 'Welcome to <strong>Jetpack %s</strong>!', 'jetpack' ),
4216 + JETPACK__VERSION
4217 + );
4218 +
4219 + if ( $active_state ) {
4220 + $titles = array();
4221 + foreach ( $active_state as $mod ) {
4222 + if ( $mod_headers = Jetpack::get_module( $mod ) ) {
4223 + $titles[] = '<strong>' . preg_replace( '/\s+(?![^<>]++>)/', '&nbsp;', $mod_headers['name'] ) . '</strong>';
4224 + }
4225 + }
4226 + if ( $titles ) {
4227 + $this->message .= '<br /><br />' . wp_sprintf( __( 'The following new modules have been activated: %l.', 'jetpack' ), $titles );
4228 + }
4229 + }
4230 +
4231 + if ( $reactive_state = Jetpack::state( 'reactivated_modules' ) ) {
4232 + $titles = array();
4233 + foreach ( explode( ',', $reactive_state ) as $mod ) {
4234 + if ( $mod_headers = Jetpack::get_module( $mod ) ) {
4235 + $titles[] = '<strong>' . preg_replace( '/\s+(?![^<>]++>)/', '&nbsp;', $mod_headers['name'] ) . '</strong>';
4236 + }
4237 + }
4238 + if ( $titles ) {
4239 + $this->message .= '<br /><br />' . wp_sprintf( __( 'The following modules have been updated: %l.', 'jetpack' ), $titles );
4240 + }
4241 + }
4242 +
4243 + $this->message .= Jetpack::jetpack_comment_notice();
4244 + break;
4245 +
4246 + case 'module_activated' :
4247 + if ( $module = Jetpack::get_module( Jetpack::state( 'module' ) ) ) {
4248 + $this->message = sprintf( __( '<strong>%s Activated!</strong> You can deactivate at any time by clicking Learn More and then Deactivate on the module card.', 'jetpack' ), $module['name'] );
4249 + $this->stat( 'module-activated', Jetpack::state( 'module' ) );
4250 + }
4251 + break;
4252 +
4253 + case 'module_deactivated' :
4254 + $modules = Jetpack::state( 'module' );
4255 + if ( !$modules ) {
4256 + break;
4257 + }
4258 +
4259 + $module_names = array();
4260 + foreach ( explode( ',', $modules ) as $module_slug ) {
4261 + $module = Jetpack::get_module( $module_slug );
4262 + if ( $module ) {
4263 + $module_names[] = $module['name'];
4264 + }
4265 +
4266 + $this->stat( 'module-deactivated', $module_slug );
4267 + }
4268 +
4269 + if ( !$module_names ) {
4270 + break;
4271 + }
4272 +
4273 + $this->message = wp_sprintf(
4274 + _nx(
4275 + '<strong>%l Deactivated!</strong> You can activate it again at any time using the activate button on the module card.',
4276 + '<strong>%l Deactivated!</strong> You can activate them again at any time using the activate buttons on their module cards.',
4277 + count( $module_names ),
4278 + '%l = list of Jetpack module/feature names',
4279 + 'jetpack'
4280 + ),
4281 + $module_names
4282 + );
4283 + break;
4284 +
4285 + case 'module_configured' :
4286 + $this->message = __( '<strong>Module settings were saved.</strong> ', 'jetpack' );
4287 + break;
4288 +
4289 + case 'already_authorized' :
4290 + $this->message = __( '<strong>Your Jetpack is already connected.</strong> ', 'jetpack' );
4291 + break;
4292 +
4293 + case 'authorized' :
4294 + $this->message = __( "<strong>You&#8217;re fueled up and ready to go.</strong> ", 'jetpack' );
4295 + $this->message .= "<br />\n";
4296 + $this->message .= __( 'The features below are now active. Click the learn more buttons to explore each feature.', 'jetpack' );
4297 + $this->message .= Jetpack::jetpack_comment_notice();
4298 + break;
4299 +
4300 + case 'linked' :
4301 + $this->message = __( "<strong>You&#8217;re fueled up and ready to go.</strong> ", 'jetpack' );
4302 + $this->message .= Jetpack::jetpack_comment_notice();
4303 + break;
4304 +
4305 + case 'unlinked' :
4306 + $user = wp_get_current_user();
4307 + $this->message = sprintf( __( '<strong>You have unlinked your account (%s) from WordPress.com.</strong>', 'jetpack' ), $user->user_login );
4308 + break;
4309 + }
4310 +
4311 + $deactivated_plugins = Jetpack::state( 'deactivated_plugins' );
4312 +
4313 + if ( !empty( $deactivated_plugins ) ) {
4314 + $deactivated_plugins = explode( ',', $deactivated_plugins );
4315 + $deactivated_titles = array();
4316 + foreach ( $deactivated_plugins as $deactivated_plugin ) {
4317 + if ( !isset( $this->plugins_to_deactivate[$deactivated_plugin] ) ) {
4318 + continue;
4319 + }
4320 +
4321 + $deactivated_titles[] = '<strong>' . str_replace( ' ', '&nbsp;', $this->plugins_to_deactivate[$deactivated_plugin][1] ) . '</strong>';
4322 + }
4323 +
4324 + if ( $deactivated_titles ) {
4325 + if ( $this->message ) {
4326 + $this->message .= "<br /><br />\n";
4327 + }
4328 +
4329 + $this->message .= wp_sprintf( _n(
4330 + 'Jetpack contains the most recent version of the old %l plugin.',
4331 + 'Jetpack contains the most recent versions of the old %l plugins.',
4332 + count( $deactivated_titles ),
4333 + 'jetpack'
4334 + ), $deactivated_titles );
4335 +
4336 + $this->message .= "<br />\n";
4337 +
4338 + $this->message .= _n(
4339 + 'The old version has been deactivated and can be removed from your site.',
4340 + 'The old versions have been deactivated and can be removed from your site.',
4341 + count( $deactivated_titles ),
4342 + 'jetpack'
4343 + );
4344 + }
4345 + }
4346 +
4347 + $this->privacy_checks = Jetpack::state( 'privacy_checks' );
4348 +
4349 + if ( $this->message || $this->error || $this->privacy_checks ) {
4350 + add_action( 'jetpack_notices', array( $this, 'admin_notices' ) );
4351 + }
4352 +
4353 + if ( isset( $_GET['configure'] ) && Jetpack::is_module( $_GET['configure'] ) && current_user_can( 'manage_options' ) ) {
4354 + do_action( 'jetpack_module_configuration_load_' . $_GET['configure'] );
4355 + }
4356 +
4357 + add_filter( 'jetpack_short_module_description', 'wptexturize' );
4358 + }
4359 +
4360 + function admin_notices() {
4361 +
4362 + if ( $this->error ) {
4363 +?>
4364 +<div id="message" class="jetpack-message jetpack-err">
4365 + <div class="squeezer">
4366 + <h4><?php echo wp_kses( $this->error, array( 'code' => true, 'strong' => true, 'br' => true, 'b' => true ) ); ?></h4>
4367 +<?php if ( $desc = Jetpack::state( 'error_description' ) ) : ?>
4368 + <p><?php echo esc_html( stripslashes( $desc ) ); ?></p>
4369 +<?php endif; ?>
4370 + </div>
4371 +</div>
4372 +<?php
4373 + }
4374 +
4375 + if ( $this->message ) {
4376 +?>
4377 +<div id="message" class="jetpack-message">
4378 + <div class="squeezer">
4379 + <h4><?php echo wp_kses( $this->message, array( 'strong' => array(), 'a' => array( 'href' => true ), 'br' => true ) ); ?></h4>
4380 + </div>
4381 +</div>
4382 +<?php
4383 +
4384 + }
4385 +
4386 + if ( $this->privacy_checks ) :
4387 + $module_names = $module_slugs = array();
4388 +
4389 + $privacy_checks = explode( ',', $this->privacy_checks );
4390 + foreach ( $privacy_checks as $module_slug ) {
4391 + $module = Jetpack::get_module( $module_slug );
4392 + if ( !$module ) {
4393 + continue;
4394 + }
4395 +
4396 + $module_slugs[] = $module_slug;
4397 + $module_names[] = "<strong>{$module['name']}</strong>";
4398 + }
4399 +
4400 + $module_slugs = join( ',', $module_slugs );
4401 +?>
4402 +<div id="message" class="jetpack-message jetpack-err">
4403 + <div class="squeezer">
4404 + <h4><strong><?php esc_html_e( 'Is this site private?', 'jetpack' ); ?></strong></h4><br />
4405 + <p><?php
4406 + echo wp_kses( wptexturize( wp_sprintf(
4407 + _nx(
4408 + "Like your site's RSS feeds, %l allows access to your posts and other content to third parties.",
4409 + "Like your site's RSS feeds, %l allow access to your posts and other content to third parties.",
4410 + count( $privacy_checks ),
4411 + '%l = list of Jetpack module/feature names',
4412 + 'jetpack'
4413 + ),
4414 + $module_names
4415 + ) ), array( 'strong' => true ) );
4416 +
4417 + echo "\n<br />\n";
4418 +
4419 + echo wp_kses( sprintf(
4420 + _nx(
4421 + 'If your site is not publicly accessible, consider <a href="%1$s" title="%2$s">deactivating this feature</a>.',
4422 + 'If your site is not publicly accessible, consider <a href="%1$s" title="%2$s">deactivating these features</a>.',
4423 + count( $privacy_checks ),
4424 + '%1$s = deactivation URL, %2$s = "Deactivate {list of Jetpack module/feature names}',
4425 + 'jetpack'
4426 + ),
4427 + wp_nonce_url(
4428 + Jetpack::admin_url( array(
4429 + 'page' => 'jetpack',
4430 + 'action' => 'deactivate',
4431 + 'module' => urlencode( $module_slugs ),
4432 + ) ),
4433 + "jetpack_deactivate-$module_slugs"
4434 + ),
4435 + esc_attr( wp_kses( wp_sprintf( _x( 'Deactivate %l', '%l = list of Jetpack module/feature names', 'jetpack' ), $module_names ), array() ) )
4436 + ), array( 'a' => array( 'href' => true, 'title' => true ) ) );
4437 + ?></p>
4438 + </div>
4439 +</div>
4440 +<?php
4441 + endif;
4442 + }
4443 +
4444 + /**
4445 + * Record a stat for later output. This will only currently output in the admin_footer.
4446 + */
4447 + function stat( $group, $detail ) {
4448 + if ( !isset( $this->stats[ $group ] ) )
4449 + $this->stats[ $group ] = array();
4450 + $this->stats[ $group ][] = $detail;
4451 + }
4452 +
4453 + /**
4454 + * Load stats pixels. $group is auto-prefixed with "x_jetpack-"
4455 + */
4456 + function do_stats( $method = '' ) {
4457 + if ( is_array( $this->stats ) && count( $this->stats ) ) {
4458 + foreach ( $this->stats as $group => $stats ) {
4459 + if ( is_array( $stats ) && count( $stats ) ) {
4460 + $args = array( "x_jetpack-{$group}" => implode( ',', $stats ) );
4461 + if ( 'server_side' === $method ) {
4462 + self::do_server_side_stat( $args );
4463 + } else {
4464 + echo '<img src="' . esc_url( self::build_stats_url( $args ) ) . '" width="1" height="1" style="display:none;" />';
4465 + }
4466 + }
4467 + unset( $this->stats[ $group ] );
4468 + }
4469 + }
4470 + }
4471 +
4472 + /**
4473 + * Runs stats code for a one-off, server-side.
4474 + *
4475 + * @param $args array|string The arguments to append to the URL. Should include `x_jetpack-{$group}={$stats}` or whatever we want to store.
4476 + *
4477 + * @return bool If it worked.
4478 + */
4479 + static function do_server_side_stat( $args ) {
4480 + $response = wp_remote_get( self::build_stats_url( $args ) );
4481 + if ( is_wp_error( $response ) )
4482 + return false;
4483 +
4484 + if ( 200 !== wp_remote_retrieve_response_code( $response ) )
4485 + return false;
4486 +
4487 + return true;
4488 + }
4489 +
4490 + /**
4491 + * Builds the stats url.
4492 + *
4493 + * @param $args array|string The arguments to append to the URL.
4494 + *
4495 + * @return string The URL to be pinged.
4496 + */
4497 + static function build_stats_url( $args ) {
4498 + $defaults = array(
4499 + 'v' => 'wpcom2',
4500 + 'rand' => md5( mt_rand( 0, 999 ) . time() ),
4501 + );
4502 + $args = wp_parse_args( $args, $defaults );
4503 + $base_url = apply_filters( 'jetpack_stats_base_url', ( is_ssl() ? 'https' : 'http' ) . '://stats.wordpress.com/g.gif' );
4504 + $url = add_query_arg( $args, $base_url );
4505 + return $url;
4506 + }
4507 +
4508 + function translate_current_user_to_role() {
4509 + foreach ( $this->capability_translations as $role => $cap ) {
4510 + if ( current_user_can( $role ) || current_user_can( $cap ) ) {
4511 + return $role;
4512 + }
4513 + }
4514 +
4515 + return false;
4516 + }
4517 +
4518 + function translate_role_to_cap( $role ) {
4519 + if ( !isset( $this->capability_translations[$role] ) ) {
4520 + return false;
4521 + }
4522 +
4523 + return $this->capability_translations[$role];
4524 + }
4525 +
4526 + function sign_role( $role ) {
4527 + if ( !$user_id = (int) get_current_user_id() ) {
4528 + return false;
4529 + }
4530 +
4531 + $token = Jetpack_Data::get_access_token();
4532 + if ( !$token || is_wp_error( $token ) ) {
4533 + return false;
4534 + }
4535 +
4536 + return $role . ':' . hash_hmac( 'md5', "{$role}|{$user_id}", $token->secret );
4537 + }
4538 +
4539 + function build_connect_url( $raw = false, $redirect = false ) {
4540 + if ( !Jetpack::get_option( 'blog_token' ) ) {
4541 + $url = $this->nonce_url_no_esc( $this->admin_url( 'action=register' ), 'jetpack-register' );
4542 + } else {
4543 + $role = $this->translate_current_user_to_role();
4544 + $signed_role = $this->sign_role( $role );
4545 +
4546 + $user = wp_get_current_user();
4547 +
4548 + $redirect = $redirect ? esc_url_raw( $redirect ) : '';
4549 +
4550 + $args = urlencode_deep( array(
4551 + 'response_type' => 'code',
4552 + 'client_id' => Jetpack::get_option( 'id' ),
4553 + 'redirect_uri' => add_query_arg( array(
4554 + 'action' => 'authorize',
4555 + '_wpnonce' => wp_create_nonce( "jetpack-authorize_{$role}_{$redirect}" ),
4556 + 'redirect' => $redirect ? urlencode( $redirect ) : false,
4557 + ), menu_page_url( 'jetpack', false ) ),
4558 + 'state' => $user->ID,
4559 + 'scope' => $signed_role,
4560 + 'user_email' => $user->user_email,
4561 + 'user_login' => $user->user_login,
4562 + 'is_active' => Jetpack::is_active(),
4563 + ) );
4564 +
4565 + $url = add_query_arg( $args, Jetpack::api_url( 'authorize' ) );
4566 + }
4567 +
4568 + return $raw ? $url : esc_url( $url );
4569 + }
4570 +
4571 + function build_reconnect_url( $raw = false ) {
4572 + $url = wp_nonce_url( $this->admin_url( 'action=reconnect' ), 'jetpack-reconnect' );
4573 + return $raw ? $url : esc_url( $url );
4574 + }
4575 +
4576 + public static function admin_url( $args = null ) {
4577 + $args = wp_parse_args( $args, array( 'page' => 'jetpack' ) );
4578 + $url = add_query_arg( $args, admin_url( 'admin.php' ) );
4579 + return $url;
4580 + }
4581 +
4582 + public static function nonce_url_no_esc( $actionurl, $action = -1, $name = '_wpnonce' ) {
4583 + $actionurl = str_replace( '&amp;', '&', $actionurl );
4584 + return add_query_arg( $name, wp_create_nonce( $action ), $actionurl );
4585 + }
4586 +
4587 + function dismiss_jetpack_notice() {
4588 + if ( isset( $_GET['jetpack-notice'] ) && 'dismiss' == $_GET['jetpack-notice'] && ! is_plugin_active_for_network( plugin_basename( __FILE__ ) ) ) {
4589 + require_once ABSPATH . 'wp-admin/includes/plugin.php';
4590 +
4591 + deactivate_plugins( plugin_basename( __FILE__ ), false, false );
4592 +
4593 + wp_safe_redirect( admin_url() . 'plugins.php?deactivate=true&plugin_status=all&paged=1&s=' );
4594 + exit;
4595 + }
4596 + }
4597 +
4598 + function admin_page() {
4599 + global $current_user;
4600 +
4601 + $role = $this->translate_current_user_to_role();
4602 + $is_connected = Jetpack::is_active();
4603 + $user_token = Jetpack_Data::get_access_token($current_user->ID);
4604 + $is_user_connected = $user_token && !is_wp_error($user_token);
4605 + $is_master_user = $current_user->ID == Jetpack::get_option( 'master_user' );
4606 + $module = false;
4607 + ?>
4608 + <div class="wrap" id="jetpack-settings">
4609 +
4610 + <h2 style="display: none"></h2> <!-- For WP JS message relocation -->
4611 +
4612 + <div id="jp-header"<?php if ( $is_connected ) : ?> class="small"<?php endif; ?>>
4613 + <div id="jp-clouds">
4614 + <?php if ( $is_connected ) : ?>
4615 + <div id="jp-disconnectors">
4616 + <?php if ( current_user_can( 'manage_options' ) ) : ?>
4617 + <div id="jp-disconnect" class="jp-disconnect">
4618 + <a href="<?php echo wp_nonce_url( Jetpack::admin_url( 'action=disconnect' ), 'jetpack-disconnect' ); ?>"><div class="deftext"><?php _e( 'Connected to WordPress.com', 'jetpack' ); ?></div><div class="hovertext"><?php _e( 'Disconnect from WordPress.com', 'jetpack' ) ?></div></a>
4619 + </div>
4620 + <?php endif; ?>
4621 + <?php if ( $is_user_connected && !$is_master_user ) : ?>
4622 + <div id="jp-unlink" class="jp-disconnect">
4623 + <a href="<?php echo wp_nonce_url( Jetpack::admin_url( 'action=unlink' ), 'jetpack-unlink' ); ?>"><div class="deftext"><?php _e( 'User linked to WordPress.com', 'jetpack' ); ?></div><div class="hovertext"><?php _e( 'Unlink user from WordPress.com', 'jetpack' ) ?></div></a>
4624 + </div>
4625 + <?php endif; ?>
4626 + </div>
4627 + <?php endif; ?>
4628 + <h3><?php _e( 'Jetpack by WordPress.com', 'jetpack' ) ?></h3>
4629 + <?php if ( !$is_connected ) : ?>
4630 + <div id="jp-notice">
4631 + <p><?php _e( 'Jetpack supercharges your self-hosted WordPress site with the awesome cloud power of WordPress.com.', 'jetpack' ); ?></p>
4632 + </div>
4633 + <?php endif; ?>
4634 + </div>
4635 + </div>
4636 +
4637 + <?php if ( isset( $_GET['jetpack-notice'] ) && 'dismiss' == $_GET['jetpack-notice'] ) : ?>
4638 + <div id="message" class="error">
4639 + <p><?php _e( 'Jetpack is network activated and notices can not be dismissed.', 'jetpack' ); ?></p>
4640 + </div>
4641 + <?php endif; ?>
4642 +
4643 + <?php do_action( 'jetpack_notices' ) ?>
4644 +
4645 + <?php
4646 + // If the connection has not been made then show the marketing text.
4647 + if ( ! Jetpack::is_development_mode() ) :
4648 + ?>
4649 + <?php if ( ! $is_connected ) : ?>
4650 +
4651 + <div id="message" class="updated jetpack-message jp-connect">
4652 + <div id="jp-dismiss" class="jetpack-close-button-container">
4653 + <a class="jetpack-close-button" href="?page=jetpack&jetpack-notice=dismiss" title="<?php _e( 'Dismiss this notice.', 'jetpack' ); ?>"><?php _e( 'Dismiss this notice.', 'jetpack' ); ?></a>
4654 + </div>
4655 + <div class="jetpack-wrap-container">
4656 + <div class="jetpack-text-container">
4657 + <h4>
4658 + <p><?php _e( "To enable all of the Jetpack features you&#8217;ll need to connect your website to WordPress.com using the button to the right. Once you&#8217;ve made the connection you&#8217;ll activate all the delightful features below.", 'jetpack' ) ?></p>
4659 + </h4>
4660 + </div>
4661 + <div class="jetpack-install-container">
4662 + <p class="submit"><a href="<?php echo $this->build_connect_url() ?>" class="button-connector" id="wpcom-connect"><?php _e( 'Connect to WordPress.com', 'jetpack' ); ?></a></p>
4663 + </div>
4664 + </div>
4665 + </div>
4666 +
4667 + <?php elseif ( ! $is_user_connected ) : ?>
4668 +
4669 + <div id="message" class="updated jetpack-message jp-connect">
4670 + <div class="jetpack-wrap-container">
4671 + <div class="jetpack-text-container">
4672 + <h4>
4673 + <p><?php _e( "To enable all of the Jetpack features you&#8217;ll need to link your account here to your WordPress.com account using the button to the right.", 'jetpack' ) ?></p>
4674 + </h4>
4675 + </div>
4676 + <div class="jetpack-install-container">
4677 + <p class="submit"><a href="<?php echo $this->build_connect_url() ?>" class="button-connector" id="wpcom-connect"><?php _e( 'Link account with WordPress.com', 'jetpack' ); ?></a></p>
4678 + </div>
4679 + </div>
4680 + </div>
4681 +
4682 + <?php else /* blog and user are connected */ : ?>
4683 + <?php /* TODO: if not master user, show user disconnect button? */ ?>
4684 + <?php endif; ?>
4685 + <?php endif; // ! Jetpack::is_development_mode() ?>
4686 +
4687 + <?php
4688 + if ( isset( $_GET['configure'] ) && Jetpack::is_module( $_GET['configure'] ) && current_user_can( 'manage_options' ) ) {
4689 + $this->admin_screen_configure_module( $_GET['configure'] );
4690 + } else {
4691 + $this->admin_screen_list_modules();
4692 + }
4693 + ?>
4694 +
4695 + <div id="survey" class="jp-survey">
4696 + <div class="jp-survey-container">
4697 + <div class="jp-survey-text">
4698 + <h4><?php _e( 'Have feedback on Jetpack?', 'jetpack' ); ?></h4>
4699 + <br />
4700 + <?php _e( 'Answer a short survey to let us know how we&#8217;re doing and what to add in the future.', 'jetpack' ); ?>
4701 + </div>
4702 + <div class="jp-survey-button-container">
4703 + <p class="submit"><?php printf( '<a id="jp-survey-button" class="button-primary" target="_blank" href="%1$s">%2$s</a>', 'http://jetpack.me/survey/?rel=' . JETPACK__VERSION, __( 'Take Survey', 'jetpack' ) ); ?></p>
4704 + </div>
4705 + </div>
4706 + </div>
4707 +
4708 + <?php if ( $is_connected && $this->current_user_is_connection_owner() ) : ?>
4709 + <p id="news-sub"><?php _e( 'Checking email updates status&hellip;', 'jetpack' ); ?></p>
4710 + <script type="text/javascript">
4711 + jQuery(document).ready(function($){
4712 + $.get( ajaxurl, { action: 'jetpack-check-news-subscription', rand: jQuery.now().toString() + Math.random().toString() }, function( data ) {
4713 + if ( 'subscribed' == data ) {
4714 + $( '#news-sub' ).html( '<?php printf(
4715 + esc_js( _x( 'You are currently subscribed to email updates. %s', '%s = Unsubscribe link', 'jetpack' ) ),
4716 + '<a href="#" class="jp-news-link button">' . esc_js( __( 'Unsubscribe', 'jetpack' ) ) . '</a>'
4717 + ); ?>' );
4718 + } else {
4719 + $( '#news-sub' ).html( '<?php printf(
4720 + esc_js( _x( 'Want to receive updates about Jetpack by email? %s', '%s = Subscribe link', 'jetpack' ) ),
4721 + '<a href="#" class="jp-news-link button-primary">' . esc_js( __( 'Subscribe', 'jetpack' ) ) . '</a>'
4722 + ); ?>' );
4723 + }
4724 + $( '.jp-news-link' ).click( function() {
4725 + $( '#news-sub' ).append( ' <img src="<?php echo esc_js( esc_url( admin_url( 'images/loading.gif' ) ) ); ?>" align="absmiddle" id="jp-news-loading" />' );
4726 + $.get( ajaxurl, { action: 'jetpack-subscribe-to-news', rand: jQuery.now().toString() + Math.random().toString() }, function( data ) {
4727 + if ( 'subscribed' == data ) {
4728 + $( '#news-sub' ).text( '<?php echo esc_js( __( 'You have been subscribed to receive email updates.', 'jetpack' ) ); ?>' );
4729 + } else {
4730 + $( '#news-sub' ).text( '<?php echo esc_js( __( 'You will no longer receive email updates about Jetpack.', 'jetpack' ) ); ?>' );
4731 + }
4732 + $( '#jp-news-loading' ).remove();
4733 + } );
4734 + return false;
4735 + } );
4736 + } );
4737 + } );
4738 + </script>
4739 + <?php endif; ?>
4740 +
4741 + <div id="jp-footer">
4742 + <p class="automattic"><?php _e( 'An <span>Automattic</span> Airline', 'jetpack' ) ?></p>
4743 + <p class="small">
4744 + <a href="http://jetpack.me/" target="_blank">Jetpack <?php echo esc_html( JETPACK__VERSION ); ?></a> |
4745 + <a href="http://automattic.com/privacy/" target="_blank"><?php _e( 'Privacy Policy', 'jetpack' ); ?></a> |
4746 + <a href="http://wordpress.com/tos/" target="_blank"><?php _e( 'Terms of Service', 'jetpack' ); ?></a> |
4747 +<?php if ( current_user_can( 'manage_options' ) ) : ?>
4748 + <a href="<?php echo Jetpack::admin_url( array( 'page' => 'jetpack-debugger' ) ); ?>"><?php _e( 'Debug', 'jetpack' ); ?></a> |
4749 +<?php endif; ?>
4750 + <a href="http://jetpack.me/support/" target="_blank"><?php _e( 'Support', 'jetpack' ); ?></a>
4751 + </p>
4752 + </div>
4753 +
4754 + <div id="jetpack-configuration" style="display:none;">
4755 + <p><img width="16" src="<?php echo esc_url( plugins_url( '_inc/images/wpspin_light-2x.gif', __FILE__ ) ); ?>" alt="Loading ..." /></p>
4756 + </div>
4757 + </div>
4758 + <?php
4759 + }
4760 +/*
4761 + function admin_page_modules() {
4762 + global $current_user;
4763 +
4764 + $role = $this->translate_current_user_to_role();
4765 + $is_connected = Jetpack::is_active();
4766 + $user_token = Jetpack_Data::get_access_token($current_user->ID);
4767 + $is_user_connected = $user_token && !is_wp_error($user_token);
4768 + $is_master_user = $current_user->ID == Jetpack::get_option( 'master_user' );
4769 + $module = false;
4770 + ?>
4771 + <div class="wrap" id="jetpack-settings">
4772 +
4773 + <h2 style="display: none"></h2> <!-- For WP JS message relocation -->
4774 +
4775 + <div id="jp-header"<?php if ( $is_connected ) : ?> class="small"<?php endif; ?>>
4776 + <div id="jp-clouds">
4777 + <?php if ( $is_connected ) : ?>
4778 + <div id="jp-disconnectors">
4779 + <?php if ( current_user_can( 'manage_options' ) ) : ?>
4780 + <div id="jp-disconnect" class="jp-disconnect">
4781 + <a href="<?php echo wp_nonce_url( Jetpack::admin_url( 'action=disconnect' ), 'jetpack-disconnect' ); ?>"><div class="deftext"><?php _e( 'Connected to WordPress.com', 'jetpack' ); ?></div><div class="hovertext"><?php _e( 'Disconnect from WordPress.com', 'jetpack' ) ?></div></a>
4782 + </div>
4783 + <?php endif; ?>
4784 + <?php if ( $is_user_connected && !$is_master_user ) : ?>
4785 + <div id="jp-unlink" class="jp-disconnect">
4786 + <a href="<?php echo wp_nonce_url( Jetpack::admin_url( 'action=unlink' ), 'jetpack-unlink' ); ?>"><div class="deftext"><?php _e( 'User linked to WordPress.com', 'jetpack' ); ?></div><div class="hovertext"><?php _e( 'Unlink user from WordPress.com', 'jetpack' ) ?></div></a>
4787 + </div>
4788 + <?php endif; ?>
4789 + </div>
4790 + <?php endif; ?>
4791 + <h3><?php _e( 'Jetpack by WordPress.com', 'jetpack' ) ?></h3>
4792 + <?php if ( !$is_connected ) : ?>
4793 + <div id="jp-notice">
4794 + <p><?php _e( 'Jetpack supercharges your self-hosted WordPress site with the awesome cloud power of WordPress.com.', 'jetpack' ); ?></p>
4795 + </div>
4796 + <?php endif; ?>
4797 + </div>
4798 + </div>
4799 +
4800 + <?php if ( isset( $_GET['jetpack-notice'] ) && 'dismiss' == $_GET['jetpack-notice'] ) : ?>
4801 + <div id="message" class="error">
4802 + <p><?php _e( 'Jetpack is network activated and notices can not be dismissed.', 'jetpack' ); ?></p>
4803 + </div>
4804 + <?php endif; ?>
4805 +
4806 + <?php do_action( 'jetpack_notices' ) ?>
4807 +
4808 + <?php
4809 + // If the connection has not been made then show the marketing text.
4810 + if ( ! Jetpack::is_development_mode() ) :
4811 + ?>
4812 + <?php if ( ! $is_connected ) : ?>
4813 +
4814 + <div id="message" class="updated jetpack-message jp-connect">
4815 + <div id="jp-dismiss" class="jetpack-close-button-container">
4816 + <a class="jetpack-close-button" href="?page=jetpack&jetpack-notice=dismiss" title="<?php _e( 'Dismiss this notice.', 'jetpack' ); ?>"><?php _e( 'Dismiss this notice.', 'jetpack' ); ?></a>
4817 + </div>
4818 + <div class="jetpack-wrap-container">
4819 + <div class="jetpack-text-container">
4820 + <h4>
4821 + <p><?php _e( "To enable all of the Jetpack features you&#8217;ll need to connect your website to WordPress.com using the button to the right. Once you&#8217;ve made the connection you&#8217;ll activate all the delightful features below.", 'jetpack' ) ?></p>
4822 + </h4>
4823 + </div>
4824 + <div class="jetpack-install-container">
4825 + <p class="submit"><a href="<?php echo $this->build_connect_url() ?>" class="button-connector" id="wpcom-connect"><?php _e( 'Connect to WordPress.com', 'jetpack' ); ?></a></p>
4826 + </div>
4827 + </div>
4828 + </div>
4829 +
4830 + <?php elseif ( ! $is_user_connected ) : ?>
4831 +
4832 + <div id="message" class="updated jetpack-message jp-connect">
4833 + <div class="jetpack-wrap-container">
4834 + <div class="jetpack-text-container">
4835 + <h4>
4836 + <p><?php _e( "To enable all of the Jetpack features you&#8217;ll need to link your account here to your WordPress.com account using the button to the right.", 'jetpack' ) ?></p>
4837 + </h4>
4838 + </div>
4839 + <div class="jetpack-install-container">
4840 + <p class="submit"><a href="<?php echo $this->build_connect_url() ?>" class="button-connector" id="wpcom-connect"><?php _e( 'Link account with WordPress.com', 'jetpack' ); ?></a></p>
4841 + </div>
4842 + </div>
4843 + </div>
4844 +
4845 + <?php else: // blog and user are connected ?>
4846 + <?php // TODO: if not master user, show user disconnect button? ?>
4847 + <?php endif; ?>
4848 + <?php endif; // ! Jetpack::is_development_mode() ?>
4849 +
4850 + <?php
4851 + if ( isset( $_GET['configure'] ) && Jetpack::is_module( $_GET['configure'] ) && current_user_can( 'manage_options' ) ) {
4852 + $this->admin_screen_configure_module( $_GET['configure'] );
4853 + } else {
4854 + $this->admin_screen_list_modules();
4855 + }
4856 + ?>
4857 +
4858 + </div>
4859 + <?php
4860 + }
4861 +/**/
4862 + function debugger_page() {
4863 + nocache_headers();
4864 + if ( !current_user_can( 'manage_options' ) ) {
4865 + die( '-1' );
4866 + }
4867 + jetpack_debug_display_handler();
4868 + exit;
4869 + }
4870 +
4871 + function admin_screen_configure_module( $module_id ) {
4872 + if ( !in_array( $module_id, Jetpack::get_active_modules() ) || !current_user_can( 'manage_options' ) )
4873 + return false; ?>
4874 +
4875 + <div id="jp-settings-screen" style="position: relative">
4876 + <h3>
4877 + <?php
4878 + $module = Jetpack::get_module( $module_id );
4879 + echo '<a href="' . menu_page_url( 'jetpack', false ) . '">' . __( 'Jetpack by WordPress.com', 'jetpack' ) . '</a> &rarr; ';
4880 + printf( __( 'Configure %s', 'jetpack' ), $module['name'] );
4881 + ?>
4882 + </h3>
4883 +
4884 + <?php do_action( 'jetpack_module_configuration_screen_' . $module_id ); ?>
4885 + </div><?php
4886 + }
4887 +
4888 + public static function sort_modules( $a, $b ) {
4889 + if ( $a['sort'] == $b['sort'] )
4890 + return 0;
4891 +
4892 + return ( $a['sort'] < $b['sort'] ) ? -1 : 1;
4893 + }
4894 +
4895 + function admin_screen_list_modules() {
4896 + require_once dirname( __FILE__ ) . '/modules/module-info.php';
4897 + $jetpack_connected = true;
4898 + if ( !Jetpack::is_active() )
4899 + $jetpack_connected = false;
4900 +
4901 + ?>
4902 + <div class="module-container">
4903 + <?php
4904 +
4905 + $avail_raw = Jetpack::get_available_modules();
4906 + $available = array();
4907 + $active = Jetpack::get_active_modules();
4908 + $counter = 0;
4909 +
4910 + foreach ( (array) $avail_raw as $module ) {
4911 + if ( $plugin = Jetpack::get_module( $module ) ) {
4912 + $plugin['module'] = $module;
4913 + $available[] = $plugin;
4914 + }
4915 + }
4916 + unset( $avail_raw );
4917 + usort( $available, array( 'Jetpack', 'sort_modules' ) );
4918 + $jetpack_version = Jetpack::get_option( 'version' );
4919 + if ( $jetpack_version ) {
4920 + list( $jetpack_version, $jetpack_version_time ) = explode( ':', $jetpack_version );
4921 + } else {
4922 + $jetpack_version = 0;
4923 + $jetpack_version_time = 0;
4924 + }
4925 +
4926 + $jetpack_old_version = Jetpack::get_option( 'old_version' );
4927 + if ( $jetpack_old_version ) {
4928 + list( $jetpack_old_version ) = explode( ':', $jetpack_old_version );
4929 + } else {
4930 + $jetpack_old_version = 0;
4931 + }
4932 + $now = time();
4933 +
4934 + foreach ( (array) $available as $module_data ) {
4935 + $module = $module_data['module'];
4936 + $activated = in_array( $module, $active );
4937 + if ( $activated ) {
4938 + $css = 'active';
4939 + $toggle = __( 'Deactivate', 'jetpack' );
4940 + $toggle_url = wp_nonce_url(
4941 + Jetpack::admin_url( array(
4942 + 'page' => 'jetpack',
4943 + 'action' => 'deactivate',
4944 + 'module' => $module
4945 + ) ),
4946 + "jetpack_deactivate-$module"
4947 + );
4948 + } else {
4949 + $css = 'inactive';
4950 + $toggle = __( 'Activate', 'jetpack' );
4951 + $toggle_url = wp_nonce_url(
4952 + Jetpack::admin_url( array(
4953 + 'page' => 'jetpack',
4954 + 'action' => 'activate',
4955 + 'module' => $module
4956 + ) ),
4957 + "jetpack_activate-$module"
4958 + );
4959 + }
4960 +
4961 + if ( $counter % 4 == 0 ) {
4962 + $classes = $css . ' jetpack-newline';
4963 + $counter = 0;
4964 + } else {
4965 + $classes = $css;
4966 + }
4967 +
4968 + $free_text = esc_html( $module_data['free'] ? __( 'Free', 'jetpack' ) : __( 'Purchase', 'jetpack' ) );
4969 + $free_text = apply_filters( 'jetpack_module_free_text_' . $module, $free_text );
4970 + $badge_text = $free_text;
4971 +
4972 + if ( ( ! $jetpack_connected && ! Jetpack::is_development_mode() ) ) {
4973 + $classes = 'x disabled';
4974 + } else if ( $jetpack_version_time + 604800 > $now ) { // 1 week
4975 + if ( version_compare( $module_data['introduced'], $jetpack_old_version, '>' ) ) {
4976 + $badge_text = esc_html__( 'New', 'jetpack' );
4977 + $classes .= ' jetpack-new-module';
4978 + } elseif ( isset( $module_data['changed'] ) && version_compare( $module_data['changed'], $jetpack_old_version, '>' ) ) {
4979 + $badge_text = esc_html__( 'Updated', 'jetpack' );
4980 + $classes .= ' jetpack-updated-module';
4981 + } else {
4982 + $badge_text = $free_text;
4983 + }
4984 + }
4985 +
4986 + ?>
4987 + <div class="jetpack-module jetpack-<?php echo $classes; ?>" id="<?php echo $module ?>">
4988 + <h3><?php echo $module_data['name']; ?></h3>
4989 + <div class="jetpack-module-description">
4990 + <div class="module-image">
4991 + <p><span class="module-image-badge"><?php echo $badge_text; ?></span><span class="module-image-free" style="display: none"><?php echo $free_text; ?></span></p>
4992 + </div>
4993 +
4994 + <p><?php echo apply_filters( 'jetpack_short_module_description', $module_data['description'], $module ); ?></p>
4995 + </div>
4996 +
4997 + <div class="jetpack-module-actions">
4998 + <?php if ( $jetpack_connected || ( Jetpack::is_development_mode() && ! $module_data['requires_connection'] ) ) : ?>
4999 + <?php if ( !$activated && current_user_can( 'manage_options' ) && apply_filters( 'jetpack_can_activate_' . $module, true ) ) : ?>
5000 + <a href="<?php echo esc_url( $toggle_url ); ?>" class="<?php echo ( 'inactive' == $css ? ' button-primary' : ' button-secondary' ); ?>"><?php echo $toggle; ?></a>&nbsp;
5001 + <?php endif; ?>
5002 +
5003 + <?php do_action( 'jetpack_learn_more_button_' . $module ) ?>
5004 +
5005 + <?php
5006 + if ( current_user_can( 'manage_options' ) && apply_filters( 'jetpack_module_configurable_' . $module, false ) ) {
5007 + echo '<a href="' . esc_url( Jetpack::module_configuration_url( $module ) ) . '" class="jetpack-configure-button button-secondary">' . __( 'Configure', 'jetpack' ) . '</a>';
5008 + }
5009 + ?><?php if ( $activated && $module_data['deactivate'] && current_user_can( 'manage_options' ) ) : ?><a style="display: none;" href="<?php echo esc_url( $toggle_url ); ?>" class="jetpack-deactivate-button button-secondary"><?php echo $toggle; ?></a>&nbsp;<?php endif; ?>
5010 +
5011 + <?php else : ?>
5012 + <?php do_action( 'jetpack_learn_more_button_' . $module ) ?>
5013 + <?php endif; ?>
5014 + </div>
5015 + </div>
5016 + <?php if ( 'inactive' == $css && $jetpack_connected && current_user_can( 'manage_options' ) && apply_filters( 'jetpack_can_activate_' . $module, true ) ) : ?>
5017 + <script type="text/javascript">
5018 + jQuery( '#<?php echo esc_js( $module ); ?>' ).bind( 'click', function(e){
5019 + if ( !jQuery(e.target).hasClass('more-info-link') )
5020 + document.location.href = '<?php echo str_replace( '&amp;', '&', esc_js( esc_url( $toggle_url ) ) ); ?>';
5021 + } );
5022 + </script>
5023 + <?php else: ?>
5024 + <style>
5025 + #<?php echo $module; ?> { cursor: default; }
5026 + </style>
5027 + <?php endif; ?>
5028 +
5029 + <div id="jp-more-info-<?php echo esc_attr( $module ); ?>" style="display:none;">
5030 + <?php
5031 + if ( $jetpack_connected && has_action( 'jetpack_module_more_info_connected_' . $module ) )
5032 + do_action( 'jetpack_module_more_info_connected_' . $module );
5033 + else
5034 + do_action( 'jetpack_module_more_info_' . $module );
5035 + ?>
5036 + </div>
5037 +
5038 + <?php
5039 + $counter++;
5040 + }
5041 +
5042 + // Add in some "Coming soon..." placeholders to fill up the current row and one more
5043 + for ( $i = 0; $i < 4; $i++ ) { ?>
5044 + <div class="jetpack-module placeholder"<?php if ( $i > 8 - $counter ) echo ' style="display: none;"'; ?>>
5045 + <h3><?php _e( 'Coming soon&#8230;', 'jetpack' ) ?></h3>
5046 + </div>
5047 + <?php
5048 + }
5049 +
5050 + echo '</div><!-- .module-container -->';
5051 + }
5052 +
5053 + function check_news_subscription() {
5054 + if ( !$this->current_user_is_connection_owner() ) {
5055 + exit;
5056 + }
5057 +
5058 + Jetpack::load_xml_rpc_client();
5059 + $xml = new Jetpack_IXR_Client( array(
5060 + 'user_id' => JETPACK_MASTER_USER,
5061 + ) );
5062 + $xml->query( 'jetpack.checkNewsSubscription' );
5063 + if ( $xml->isError() ) {
5064 + printf( '%s: %s', $xml->getErrorCode(), $xml->getErrorMessage() );
5065 + } else {
5066 + print_r( $xml->getResponse() );
5067 + }
5068 + exit;
5069 + }
5070 +
5071 + function subscribe_to_news() {
5072 + if ( !$this->current_user_is_connection_owner() ) {
5073 + exit;
5074 + }
5075 +
5076 + Jetpack::load_xml_rpc_client();
5077 + $xml = new Jetpack_IXR_Client( array(
5078 + 'user_id' => JETPACK_MASTER_USER,
5079 + ) );
5080 + $xml->query( 'jetpack.subscribeToNews' );
5081 + if ( $xml->isError() ) {
5082 + printf( '%s: %s', $xml->getErrorCode(), $xml->getErrorMessage() );
5083 + } else {
5084 + print_r( $xml->getResponse() );
5085 + }
5086 + exit;
5087 + }
5088 +
5089 +/* Client API */
5090 +
5091 + /**
5092 + * Returns the requested Jetpack API URL
5093 + *
5094 + * @return string
5095 + */
5096 + public static function api_url( $relative_url ) {
5097 + return trailingslashit( JETPACK__API_BASE . $relative_url ) . JETPACK__API_VERSION . '/';
5098 + }
5099 +
5100 + /**
5101 + * Some hosts disable the OpenSSL extension and so cannot make outgoing HTTPS requsets
5102 + */
5103 + public static function fix_url_for_bad_hosts( $url, &$args ) {
5104 + if ( 0 !== strpos( $url, 'https://' ) ) {
5105 + return $url;
5106 + }
5107 +
5108 + switch ( JETPACK_CLIENT__HTTPS ) {
5109 + case 'ALWAYS' :
5110 + return $url;
5111 + case 'NEVER' :
5112 + return self::force_url_to_non_ssl( $url );
5113 + // default : case 'AUTO' :
5114 + }
5115 +
5116 + $jetpack = Jetpack::init();
5117 +
5118 + // Yay! Your host is good!
5119 + if ( self::permit_ssl() && wp_http_supports( array( 'ssl' => true ) ) ) {
5120 + return $url;
5121 + }
5122 +
5123 + // Boo! Your host is bad and makes Jetpack cry!
5124 + return self::force_url_to_non_ssl( $url );
5125 + }
5126 +
5127 + /**
5128 + * Checks to see if the URL is using SSL to connect with Jetpack
5129 + *
5130 + * @since 2.3.3
5131 + * @return boolean
5132 + */
5133 + public static function permit_ssl( $force_recheck = false ) {
5134 + // Do some fancy tests to see if ssl is being supported
5135 + if ( $force_recheck || false === ( $ssl = get_transient( 'jetpack_https_test' ) ) ) {
5136 +
5137 + if ( 'https' !== substr( JETPACK__API_BASE, 0, 5 ) ) {
5138 + $ssl = 0;
5139 + } else {
5140 + switch ( JETPACK_CLIENT__HTTPS ) {
5141 + case 'NEVER':
5142 + $ssl = 0;
5143 + break;
5144 + case 'ALWAYS':
5145 + case 'AUTO':
5146 + default:
5147 + $ssl = 1;
5148 + break;
5149 + }
5150 +
5151 + // If it's not 'NEVER', test to see
5152 + if ( $ssl ) {
5153 + $response = wp_remote_get( JETPACK__API_BASE . 'test/1/' );
5154 + if ( is_wp_error( $response ) || ( 'OK' !== wp_remote_retrieve_body( $response ) ) ) {
5155 + $ssl = 0;
5156 + }
5157 + }
5158 + }
5159 + set_transient( 'jetpack_https_test', $ssl, DAY_IN_SECONDS );
5160 + }
5161 +
5162 + return (bool) $ssl;
5163 + }
5164 +
5165 + /**
5166 + * Take any URL, and if it starts with https:// change it to http://
5167 + */
5168 + public static function force_url_to_non_ssl( $url ) {
5169 + return preg_replace( '#^https://#i', 'http://', $url );
5170 + }
5171 +
5172 + /*
5173 + * Displays an admin_notice, alerting the user to their JETPACK_CLIENT__HTTPS constant being 'ALWAYS' but SSL isn't working.
5174 + */
5175 + public function alert_required_ssl_fail() {
5176 + if ( ! current_user_can( 'manage_options' ) )
5177 + return;
5178 + ?>
5179 +
5180 + <div id="message" class="error jetpack-message jp-identity-crisis">
5181 + <div class="jetpack-wrap-container">
5182 + <div class="jetpack-text-container">
5183 + <h3><?php _e( 'Something is being cranky!', 'jetpack' ); ?></h3>
5184 + <p><?php _e( 'Your site is configured to only permit SSL connections to Jetpack, but SSL connections don\'t seem to be functional!', 'jetpack' ); ?></p>
5185 + </div>
5186 + </div>
5187 + </div>
5188 +
5189 + <?php
5190 + }
5191 +
5192 + /**
5193 + * Returns the Jetpack XML-RPC API
5194 + *
5195 + * @return string
5196 + */
5197 + public static function xmlrpc_api_url() {
5198 + $base = preg_replace( '#(https?://[^?/]+)(/?.*)?$#', '\\1', JETPACK__API_BASE );
5199 + return untrailingslashit( $base ) . '/xmlrpc.php';
5200 + }
5201 +
5202 + /**
5203 + * @return bool|WP_Error
5204 + */
5205 + public static function register() {
5206 + Jetpack::update_option( 'register', wp_generate_password( 32, false ) . ':' . wp_generate_password( 32, false ) . ':' . ( time() + 600 ) );
5207 +
5208 + @list( $secret_1, $secret_2, $secret_eol ) = explode( ':', Jetpack::get_option( 'register' ) );
5209 + if ( empty( $secret_1 ) || empty( $secret_2 ) || empty( $secret_eol ) || $secret_eol < time() )
5210 + return new Jetpack_Error( 'missing_secrets' );
5211 +
5212 + $timeout = (int) ini_get( 'max_execution_time' );
5213 + if ( !$timeout )
5214 + $timeout = 30;
5215 + $timeout = intval( $timeout / 2 );
5216 +
5217 + $gmt_offset = get_option( 'gmt_offset' );
5218 + if ( !$gmt_offset ) {
5219 + $gmt_offset = 0;
5220 + }
5221 +
5222 + $stats_options = get_option( 'stats_options' );
5223 + $stats_id = isset($stats_options['blog_id']) ? $stats_options['blog_id'] : null;
5224 +
5225 + $args = array(
5226 + 'method' => 'POST',
5227 + 'body' => array(
5228 + 'siteurl' => site_url(),
5229 + 'home' => home_url(),
5230 + 'gmt_offset' => $gmt_offset,
5231 + 'timezone_string' => (string) get_option( 'timezone_string' ),
5232 + 'site_name' => (string) get_option( 'blogname' ),
5233 + 'secret_1' => $secret_1,
5234 + 'secret_2' => $secret_2,
5235 + 'site_lang' => get_locale(),
5236 + 'timeout' => $timeout,
5237 + 'stats_id' => $stats_id,
5238 + ),
5239 + 'headers' => array(
5240 + 'Accept' => 'application/json',
5241 + ),
5242 + 'timeout' => $timeout,
5243 + );
5244 + $response = Jetpack_Client::_wp_remote_request( Jetpack::fix_url_for_bad_hosts( Jetpack::api_url( 'register' ), $args ), $args, true );
5245 +
5246 + if ( is_wp_error( $response ) ) {
5247 + return new Jetpack_Error( 'register_http_request_failed', $response->get_error_message() );
5248 + }
5249 +
5250 + $code = wp_remote_retrieve_response_code( $response );
5251 + $entity = wp_remote_retrieve_body( $response );
5252 +
5253 + if ( $entity )
5254 + $json = json_decode( $entity );
5255 + else
5256 + $json = false;
5257 +
5258 + $code_type = intval( $code / 100 );
5259 + if ( 5 == $code_type ) {
5260 + return new Jetpack_Error( 'wpcom_5??', sprintf( __( 'Error Details: %s', 'jetpack' ), $code ), $code );
5261 + } elseif ( 408 == $code ) {
5262 + return new Jetpack_Error( 'wpcom_408', sprintf( __( 'Error Details: %s', 'jetpack' ), $code ), $code );
5263 + } elseif ( !empty( $json->error ) ) {
5264 + $error_description = isset( $json->error_description ) ? sprintf( __( 'Error Details: %s', 'jetpack' ), (string) $json->error_description ) : '';
5265 + return new Jetpack_Error( (string) $json->error, $error_description, $code );
5266 + } elseif ( 200 != $code ) {
5267 + return new Jetpack_Error( 'wpcom_bad_response', sprintf( __( 'Error Details: %s', 'jetpack' ), $code ), $code );
5268 + }
5269 +
5270 + // Jetpack ID error block
5271 + if ( empty( $json->jetpack_id ) ) {
5272 + return new Jetpack_Error( 'jetpack_id', sprintf( __( 'Error Details: Jetpack ID is empty. Do not publicly post this error message! %s', 'jetpack' ), $entity ), $entity );
5273 + } elseif ( ! is_scalar( $json->jetpack_id ) ) {
5274 + return new Jetpack_Error( 'jetpack_id', sprintf( __( 'Error Details: Jetpack ID is not a scalar. Do not publicly post this error message! %s', 'jetpack' ) , $entity ), $entity );
5275 + } elseif ( preg_match( '/[^0-9]/', $json->jetpack_id ) ) {
5276 + return new Jetpack_Error( 'jetpack_id', sprintf( __( 'Error Details: Jetpack ID begins with a numeral. Do not publicly post this error message! %s', 'jetpack' ) , $entity ), $entity);
5277 + }
5278 +
5279 + if ( empty( $json->jetpack_secret ) || !is_string( $json->jetpack_secret ) )
5280 + return new Jetpack_Error( 'jetpack_secret', '', $code );
5281 +
5282 + if ( isset( $json->jetpack_public ) ) {
5283 + $jetpack_public = (int) $json->jetpack_public;
5284 + } else {
5285 + $jetpack_public = false;
5286 + }
5287 +
5288 + Jetpack::update_options( array(
5289 + 'id' => (int) $json->jetpack_id,
5290 + 'blog_token' => (string) $json->jetpack_secret,
5291 + 'public' => $jetpack_public,
5292 + ) );
5293 +
5294 + return true;
5295 + }
5296 +
5297 +
5298 +/* Client Server API */
5299 +
5300 + /**
5301 + * Loads the Jetpack XML-RPC client
5302 + */
5303 + public static function load_xml_rpc_client() {
5304 + require_once ABSPATH . WPINC . '/class-IXR.php';
5305 + require_once dirname( __FILE__ ) . '/class.jetpack-ixr-client.php';
5306 + }
5307 +
5308 + /**
5309 + * Authenticates XML-RPC and other requests from the Jetpack Server
5310 + */
5311 + function authenticate_jetpack( $user, $username, $password ) {
5312 + if ( is_a( $user, 'WP_User' ) ) {
5313 + return $user;
5314 + }
5315 +
5316 + // It's not for us
5317 + if ( !isset( $_GET['token'] ) || empty( $_GET['signature'] ) ) {
5318 + return $user;
5319 + }
5320 +
5321 + @list( $token_key, $version, $user_id ) = explode( ':', $_GET['token'] );
5322 + if (
5323 + empty( $token_key )
5324 + ||
5325 + empty( $version ) || strval( JETPACK__API_VERSION ) !== $version
5326 + ||
5327 + empty( $user_id ) || !ctype_digit( $user_id ) || !get_userdata( $user_id ) // only handle user_tokens for now, not blog_tokens
5328 + ) {
5329 + return $user;
5330 + }
5331 +
5332 + $token = Jetpack_Data::get_access_token( $user_id );
5333 + if ( !$token ) {
5334 + return $user;
5335 + }
5336 +
5337 + if ( 0 !== strpos( $token->secret, "$token_key." ) ) {
5338 + return $user;
5339 + }
5340 +
5341 + require_once dirname( __FILE__ ) . '/class.jetpack-signature.php';
5342 +
5343 + $jetpack_signature = new Jetpack_Signature( $token->secret, (int) Jetpack::get_option( 'time_diff' ) );
5344 + if ( isset( $_POST['_jetpack_is_multipart'] ) ) {
5345 + $post_data = $_POST;
5346 + $file_hashes = array();
5347 + foreach ( $post_data as $post_data_key => $post_data_value ) {
5348 + if ( 0 !== strpos( $post_data_key, '_jetpack_file_hmac_' ) ) {
5349 + continue;
5350 + }
5351 + $post_data_key = substr( $post_data_key, strlen( '_jetpack_file_hmac_' ) );
5352 + $file_hashes[$post_data_key] = $post_data_value;
5353 + }
5354 +
5355 + foreach ( $file_hashes as $post_data_key => $post_data_value ) {
5356 + unset( $post_data["_jetpack_file_hmac_{$post_data_key}"] );
5357 + $post_data[$post_data_key] = $post_data_value;
5358 + }
5359 +
5360 + ksort( $post_data );
5361 +
5362 + $body = http_build_query( stripslashes_deep( $post_data ) );
5363 + } elseif ( is_null( $this->HTTP_RAW_POST_DATA ) ) {
5364 + $body = file_get_contents( 'php://input' );
5365 + } else {
5366 + $body = null;
5367 + }
5368 + $signature = $jetpack_signature->sign_current_request( array(
5369 + 'body' => is_null( $body ) ? $this->HTTP_RAW_POST_DATA : $body
5370 + ) );
5371 +
5372 + if ( !$signature ) {
5373 + return $user;
5374 + } else if ( is_wp_error( $signature ) ) {
5375 + return $signature;
5376 + } else if ( $signature !== $_GET['signature'] ) {
5377 + return $user;
5378 + }
5379 +
5380 + $timestamp = (int) $_GET['timestamp'];
5381 + $nonce = stripslashes( (string) $_GET['nonce'] );
5382 +
5383 + if ( !$this->add_nonce( $timestamp, $nonce ) ) {
5384 + return $user;
5385 + }
5386 +
5387 + nocache_headers();
5388 +
5389 + return new WP_User( $token->external_user_id );
5390 + }
5391 +
5392 + function add_nonce( $timestamp, $nonce ) {
5393 + global $wpdb;
5394 + static $nonces_used_this_request = array();
5395 +
5396 + if ( isset( $nonces_used_this_request["$timestamp:$nonce"] ) ) {
5397 + return $nonces_used_this_request["$timestamp:$nonce"];
5398 + }
5399 +
5400 + // This should always have gone through Jetpack_Signature::sign_request() first to check $timestamp an $nonce
5401 + $timestamp = (int) $timestamp;
5402 + $nonce = $wpdb->escape( $nonce );
5403 +
5404 + // Raw query so we can avoid races: add_option will also update
5405 + $show_errors = $wpdb->show_errors( false );
5406 + $return = $wpdb->query( $wpdb->prepare(
5407 + "INSERT INTO `$wpdb->options` (`option_name`, `option_value`, `autoload`) VALUES (%s, %s, %s)",
5408 + "jetpack_nonce_{$timestamp}_{$nonce}",
5409 + time(),
5410 + 'no'
5411 + ) );
5412 + $wpdb->show_errors( $show_errors );
5413 +
5414 + $nonces_used_this_request["$timestamp:$nonce"] = $return;
5415 +
5416 + return $return;
5417 + }
5418 +
5419 + /**
5420 + * In some setups, $HTTP_RAW_POST_DATA can be emptied during some IXR_Server paths since it is passed by reference to various methods.
5421 + * Capture it here so we can verify the signature later.
5422 + */
5423 + function xmlrpc_methods( $methods ) {
5424 + $this->HTTP_RAW_POST_DATA = $GLOBALS['HTTP_RAW_POST_DATA'];
5425 + return $methods;
5426 + }
5427 +
5428 + function xmlrpc_options( $options ) {
5429 + $options['jetpack_version'] = array(
5430 + 'desc' => __( 'Jetpack Plugin Version' , 'jetpack'),
5431 + 'readonly' => true,
5432 + 'value' => JETPACK__VERSION,
5433 + );
5434 +
5435 + $options['jetpack_client_id'] = array(
5436 + 'desc' => __( 'The Client ID/WP.com Blog ID of this site' , 'jetpack'),
5437 + 'readonly' => true,
5438 + 'value' => Jetpack::get_option( 'id' ),
5439 + );
5440 + return $options;
5441 + }
5442 +
5443 + public static function clean_nonces( $all = false ) {
5444 + global $wpdb;
5445 +
5446 + $sql = "DELETE FROM `$wpdb->options` WHERE `option_name` LIKE %s";
5447 + $sql_args = array( like_escape( 'jetpack_nonce_' ) . '%' );
5448 +
5449 + if ( true !== $all ) {
5450 + $sql .= ' AND CAST( `option_value` AS UNSIGNED ) < %d';
5451 + $sql_args[] = time() - 3600;
5452 + }
5453 +
5454 + $sql .= ' LIMIT 100';
5455 +
5456 + $sql = $wpdb->prepare( $sql, $sql_args );
5457 +
5458 + for ( $i = 0; $i < 1000; $i++ ) {
5459 + if ( !$wpdb->query( $sql ) ) {
5460 + break;
5461 + }
5462 + }
5463 + }
5464 +
5465 + /**
5466 + * State is passed via cookies from one request to the next, but never to subsequent requests.
5467 + * SET: state( $key, $value );
5468 + * GET: $value = state( $key );
5469 + *
5470 + * @param string $key
5471 + * @param string $value
5472 + * @param bool $restate private
5473 + */
5474 + public static function state( $key = null, $value = null, $restate = false ) {
5475 + static $state = array();
5476 + static $path, $domain;
5477 + if ( !isset( $path ) ) {
5478 + require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
5479 + $admin_url = Jetpack::admin_url();
5480 + $bits = parse_url( $admin_url );
5481 +
5482 + if ( is_array( $bits ) ) {
5483 + $path = ( isset( $bits['path'] ) ) ? dirname( $bits['path'] ) : null;
5484 + $domain = ( isset( $bits['host'] ) ) ? $bits['host'] : null;
5485 + } else {
5486 + $path = $domain = null;
5487 + }
5488 + }
5489 +
5490 + // Extract state from cookies and delete cookies
5491 + if ( isset( $_COOKIE[ 'jetpackState' ] ) && is_array( $_COOKIE[ 'jetpackState' ] ) ) {
5492 + $yum = $_COOKIE[ 'jetpackState' ];
5493 + unset( $_COOKIE[ 'jetpackState' ] );
5494 + foreach ( $yum as $k => $v ) {
5495 + if ( strlen( $v ) )
5496 + $state[ $k ] = $v;
5497 + setcookie( "jetpackState[$k]", false, 0, $path, $domain );
5498 + }
5499 + }
5500 +
5501 + if ( $restate ) {
5502 + foreach ( $state as $k => $v ) {
5503 + setcookie( "jetpackState[$k]", $v, 0, $path, $domain );
5504 + }
5505 + return;
5506 + }
5507 +
5508 + // Get a state variable
5509 + if ( isset( $key ) && !isset( $value ) ) {
5510 + if ( array_key_exists( $key, $state ) )
5511 + return $state[ $key ];
5512 + return null;
5513 + }
5514 +
5515 + // Set a state variable
5516 + if ( isset ( $key ) && isset( $value ) ) {
5517 + $state[ $key ] = $value;
5518 + setcookie( "jetpackState[$key]", $value, 0, $path, $domain );
5519 + }
5520 + }
5521 +
5522 + public static function restate() {
5523 + Jetpack::state( null, null, true );
5524 + }
5525 +
5526 + public static function check_privacy( $file ) {
5527 + static $is_site_publicly_accessible = null;
5528 +
5529 + if ( is_null( $is_site_publicly_accessible ) ) {
5530 + $is_site_publicly_accessible = false;
5531 +
5532 + Jetpack::load_xml_rpc_client();
5533 + $rpc = new Jetpack_IXR_Client();
5534 +
5535 + $success = $rpc->query( 'jetpack.isSitePubliclyAccessible', home_url() );
5536 + if ( $success ) {
5537 + $response = $rpc->getResponse();
5538 + if ( $response ) {
5539 + $is_site_publicly_accessible = true;
5540 + }
5541 + }
5542 +
5543 + Jetpack::update_option( 'public', (int) $is_site_publicly_accessible );
5544 + }
5545 +
5546 + if ( $is_site_publicly_accessible ) {
5547 + return;
5548 + }
5549 +
5550 + $module_slug = self::get_module_slug( $file );
5551 +
5552 + $privacy_checks = Jetpack::state( 'privacy_checks' );
5553 + if ( !$privacy_checks ) {
5554 + $privacy_checks = $module_slug;
5555 + } else {
5556 + $privacy_checks .= ",$module_slug";
5557 + }
5558 +
5559 + Jetpack::state( 'privacy_checks', $privacy_checks );
5560 + }
5561 +
5562 + /**
5563 + * Helper method for multicall XMLRPC.
5564 + */
5565 + public static function xmlrpc_async_call() {
5566 + global $blog_id;
5567 + static $clients = array();
5568 +
5569 + $client_blog_id = is_multisite() ? $blog_id : 0;
5570 +
5571 + if ( !isset( $clients[$client_blog_id] ) ) {
5572 + Jetpack::load_xml_rpc_client();
5573 + $clients[$client_blog_id] = new Jetpack_IXR_ClientMulticall( array(
5574 + 'user_id' => JETPACK_MASTER_USER,
5575 + ) );
5576 + ignore_user_abort( true );
5577 + add_action( 'shutdown', array( 'Jetpack', 'xmlrpc_async_call' ) );
5578 + }
5579 +
5580 + $args = func_get_args();
5581 +
5582 + if ( !empty( $args[0] ) ) {
5583 + call_user_func_array( array( $clients[$client_blog_id], 'addCall' ), $args );
5584 + } elseif ( is_multisite() ) {
5585 + foreach ( $clients as $client_blog_id => $client ) {
5586 + if ( !$client_blog_id || empty( $client->calls ) ) {
5587 + continue;
5588 + }
5589 +
5590 + $switch_success = switch_to_blog( $client_blog_id, true );
5591 + if ( !$switch_success ) {
5592 + continue;
5593 + }
5594 +
5595 + flush();
5596 + $client->query();
5597 +
5598 + restore_current_blog();
5599 + }
5600 + } else {
5601 + if ( isset( $clients[0] ) && !empty( $clients[0]->calls ) ) {
5602 + flush();
5603 + $clients[0]->query();
5604 + }
5605 + }
5606 + }
5607 +
5608 + public static function staticize_subdomain( $url ) {
5609 + $host = parse_url( $url, PHP_URL_HOST );
5610 + if ( !preg_match( '/.?(?:wordpress|wp)\.com$/', $host ) ) {
5611 + return $url;
5612 + }
5613 +
5614 + if ( is_ssl() ) {
5615 + return preg_replace( '|https?://[^/]++/|', 'https://s-ssl.wordpress.com/', $url );
5616 + }
5617 +
5618 + srand( crc32( basename( $url ) ) );
5619 + $static_counter = rand( 0, 2 );
5620 + srand(); // this resets everything that relies on this, like array_rand() and shuffle()
5621 +
5622 + return preg_replace( '|://[^/]+?/|', "://s$static_counter.wp.com/", $url );
5623 + }
5624 +
5625 +/* JSON API Authorization */
5626 +
5627 + /**
5628 + * Handles the login action for Authorizing the JSON API
5629 + */
5630 + function login_form_json_api_authorization() {
5631 + $this->verify_json_api_authorization_request();
5632 +
5633 + add_action( 'wp_login', array( &$this, 'store_json_api_authorization_token' ), 10, 2 );
5634 +
5635 + add_action( 'login_message', array( &$this, 'login_message_json_api_authorization' ) );
5636 + add_action( 'login_form', array( &$this, 'preserve_action_in_login_form_for_json_api_authorization' ) );
5637 + add_filter( 'site_url', array( &$this, 'post_login_form_to_signed_url' ), 10, 3 );
5638 + }
5639 +
5640 + // Make sure the login form is POSTed to the signed URL so we can reverify the request
5641 + function post_login_form_to_signed_url( $url, $path, $scheme ) {
5642 + if ( 'wp-login.php' !== $path || 'login_post' !== $scheme ) {
5643 + return $url;
5644 + }
5645 +
5646 + return "$url?{$_SERVER['QUERY_STRING']}";
5647 + }
5648 +
5649 + // Make sure the POSTed request is handled by the same action
5650 + function preserve_action_in_login_form_for_json_api_authorization() {
5651 + echo "<input type='hidden' name='action' value='jetpack_json_api_authorization' />\n";
5652 + }
5653 +
5654 + // If someone logs in to approve API access, store the Access Code in usermeta
5655 + function store_json_api_authorization_token( $user_login, $user ) {
5656 + add_filter( 'login_redirect', array( &$this, 'add_token_to_login_redirect_json_api_authorization' ), 10, 3 );
5657 + add_filter( 'allowed_redirect_hosts', array( &$this, 'allow_wpcom_public_api_domain' ) );
5658 + $token = wp_generate_password( 32, false );
5659 + update_user_meta( $user->ID, 'jetpack_json_api_' . $this->json_api_authorization_request['client_id'], $token );
5660 + }
5661 +
5662 + // Add public-api.wordpress.com to the safe redirect whitelist - only added when someone allows API access
5663 + function allow_wpcom_public_api_domain( $domains ) {
5664 + $domains[] = 'public-api.wordpress.com';
5665 + return $domains;
5666 + }
5667 +
5668 + // Add the Access Code details to the public-api.wordpress.com redirect
5669 + function add_token_to_login_redirect_json_api_authorization( $redirect_to, $original_redirect_to, $user ) {
5670 + return add_query_arg( urlencode_deep( array(
5671 + 'jetpack-code' => get_user_meta( $user->ID, 'jetpack_json_api_' . $this->json_api_authorization_request['client_id'], true ),
5672 + 'jetpack-user-id' => (int) $user->ID,
5673 + 'jetpack-state' => $this->json_api_authorization_request['state'],
5674 + ) ), $redirect_to );
5675 + }
5676 +
5677 + // Verifies the request by checking the signature
5678 + function verify_json_api_authorization_request() {
5679 + require_once dirname( __FILE__ ) . '/class.jetpack-signature.php';
5680 +
5681 + $token = Jetpack_Data::get_access_token( JETPACK_MASTER_USER );
5682 + if ( !$token || empty( $token->secret ) ) {
5683 + wp_die( __( 'You must connect your Jetpack plugin to WordPress.com to use this feature.' , 'jetpack') );
5684 + }
5685 +
5686 + $die_error = __( 'Someone may be trying to trick you into giving them access to your site. Or it could be you just encountered a bug :). Either way, please close this window.', 'jetpack' );
5687 +
5688 + $jetpack_signature = new Jetpack_Signature( $token->secret, (int) Jetpack::get_option( 'time_diff' ) );
5689 + $signature = $jetpack_signature->sign_current_request( array( 'body' => null, 'method' => 'GET' ) );
5690 + if ( !$signature ) {
5691 + wp_die( $die_error );
5692 + } else if ( is_wp_error( $signature ) ) {
5693 + wp_die( $die_error );
5694 + } else if ( $signature !== $_GET['signature'] ) {
5695 + if ( is_ssl() ) {
5696 + // If we signed an HTTP request on the Jetpack Servers, but got redirected to HTTPS by the local blog, check the HTTP signature as well
5697 + $signature = $jetpack_signature->sign_current_request( array( 'scheme' => 'http', 'body' => null, 'method' => 'GET' ) );
5698 + if ( !$signature || is_wp_error( $signature ) || $signature !== $_GET['signature'] ) {
5699 + wp_die( $die_error );
5700 + }
5701 + } else {
5702 + wp_die( $die_error );
5703 + }
5704 + }
5705 +
5706 + $timestamp = (int) $_GET['timestamp'];
5707 + $nonce = stripslashes( (string) $_GET['nonce'] );
5708 +
5709 + if ( !$this->add_nonce( $timestamp, $nonce ) ) {
5710 + // De-nonce the nonce, at least for 5 minutes.
5711 + // We have to reuse this nonce at least once (used the first time when the initial request is made, used a second time when the login form is POSTed)
5712 + $old_nonce_time = get_option( "jetpack_nonce_{$timestamp}_{$nonce}" );
5713 + if ( $old_nonce_time < time() - 300 ) {
5714 + wp_die( __( 'The authorization process expired. Please go back and try again.' , 'jetpack') );
5715 + }
5716 + }
5717 +
5718 + $data = json_decode( base64_decode( stripslashes( $_GET['data'] ) ) );
5719 + $data_filters = array(
5720 + 'state' => 'opaque',
5721 + 'client_id' => 'int',
5722 + 'client_title' => 'string',
5723 + 'client_image' => 'url',
5724 + );
5725 +
5726 + foreach ( $data_filters as $key => $sanitation ) {
5727 + if ( !isset( $data->$key ) ) {
5728 + wp_die( $die_error );
5729 + }
5730 +
5731 + switch ( $sanitation ) {
5732 + case 'int' :
5733 + $this->json_api_authorization_request[$key] = (int) $data->$key;
5734 + break;
5735 + case 'opaque' :
5736 + $this->json_api_authorization_request[$key] = (string) $data->$key;
5737 + break;
5738 + case 'string' :
5739 + $this->json_api_authorization_request[$key] = wp_kses( (string) $data->$key, array() );
5740 + break;
5741 + case 'url' :
5742 + $this->json_api_authorization_request[$key] = esc_url_raw( (string) $data->$key );
5743 + break;
5744 + }
5745 + }
5746 +
5747 + if ( empty( $this->json_api_authorization_request['client_id'] ) ) {
5748 + wp_die( $die_error );
5749 + }
5750 + }
5751 +
5752 + function login_message_json_api_authorization( $message ) {
5753 + return '<p class="message">' . sprintf(
5754 + esc_html__( '%s wants to access your site&#8217;s data. Log in to authorize that access.' , 'jetpack'),
5755 + '<strong>' . esc_html( $this->json_api_authorization_request['client_title'] ) . '</strong>'
5756 + ) . '<img src="' . esc_url( $this->json_api_authorization_request['client_image'] ) . '" /></p>';
5757 + }
5758 +
5759 + /**
5760 + * Get $content_width, but with a <s>twist</s> filter.
5761 + */
5762 + public static function get_content_width() {
5763 + return apply_filters( 'jetpack_content_width', $GLOBALS['content_width'] );
5764 + }
5765 +
5766 + /**
5767 + * Centralize the function here until it gets added to core.
5768 + *
5769 + * @param int|string|object $id_or_email A user ID, email address, or comment object
5770 + * @param int $size Size of the avatar image
5771 + * @param string $default URL to a default image to use if no avatar is available
5772 + * @param bool $force_display Whether to force it to return an avatar even if show_avatars is disabled
5773 + *
5774 + * @return array First element is the URL, second is the class.
5775 + */
5776 + public static function get_avatar_url( $id_or_email, $size = 96, $default = '', $force_display = false ) {
5777 + // Don't bother adding the __return_true filter if it's already there.
5778 + $has_filter = has_filter( 'pre_option_show_avatars', '__return_true' );
5779 +
5780 + if ( $force_display && ! $has_filter )
5781 + add_filter( 'pre_option_show_avatars', '__return_true' );
5782 +
5783 + $avatar = get_avatar( $id_or_email, $size, $default );
5784 +
5785 + if ( $force_display && ! $has_filter )
5786 + remove_filter( 'pre_option_show_avatars', '__return_true' );
5787 +
5788 + // If no data, fail out.
5789 + if ( is_wp_error( $avatar ) || ! $avatar )
5790 + return array( null, null );
5791 +
5792 + // Pull out the URL. If it's not there, fail out.
5793 + if ( ! preg_match( '/src=["\']([^"\']+)["\']/', $avatar, $url_matches ) )
5794 + return array( null, null );
5795 + $url = wp_specialchars_decode( $url_matches[1], ENT_QUOTES );
5796 +
5797 + // Pull out the class, but it's not a big deal if it's missing.
5798 + $class = '';
5799 + if ( preg_match( '/class=["\']([^"\']+)["\']/', $avatar, $class_matches ) )
5800 + $class = wp_specialchars_decode( $class_matches[1], ENT_QUOTES );
5801 +
5802 + return array( $url, $class );
5803 + }
5804 +
5805 + /*
5806 + * Pings the WordPress.com Mirror Site for the specified options.
5807 + *
5808 + * @param string|array $option_names The option names to request from the WordPress.com Mirror Site
5809 + *
5810 + * @return array An associative array of the option values as stored in the WordPress.com Mirror Site
5811 + */
5812 + public static function get_cloud_site_options( $option_names ) {
5813 + $option_names = array_filter( (array) $option_names, 'is_string' );
5814 +
5815 + Jetpack::load_xml_rpc_client();
5816 + $xml = new Jetpack_IXR_Client( array(
5817 + 'user_id' => get_current_user_id(),
5818 + ) );
5819 + $xml->query( 'jetpack.fetchSiteOptions', $option_names );
5820 + if ( $xml->isError() ) {
5821 + return array_flip( $option_names );
5822 + }
5823 + $cloud_site_options = $xml->getResponse();
5824 +
5825 + // If we want to intentionally jumble the results to test it ...
5826 + if( isset( $_GET['spoof_identity_crisis'] ) ) {
5827 + foreach( $cloud_site_options as $key => $value ) {
5828 + $cloud_site_options[ $key ] = wp_generate_password();
5829 + }
5830 + }
5831 + return $cloud_site_options;
5832 + }
5833 +
5834 + /*
5835 + * Checks to make sure that local options have the same values as remote options. Will cache the results for up to 24 hours.
5836 + *
5837 + * @param bool $force_recheck Whether to ignore any cached transient and manually re-check.
5838 + *
5839 + * @return array An array of options that do not match. If everything is good, it will evaluate to false.
5840 + */
5841 + public static function check_identity_crisis( $force_recheck = false ) {
5842 + if ( ! current_user_can( 'manage_options' ) )
5843 + return false;
5844 +
5845 + if ( ! Jetpack::is_active() || Jetpack::is_development_mode() )
5846 + return false;
5847 +
5848 + if ( isset( $_GET['spoof_identity_crisis'] ) )
5849 + $force_recheck = true;
5850 +
5851 + if ( $force_recheck || false === ( $errors = get_transient( 'jetpack_has_identity_crisis' ) ) ) {
5852 + $options_to_check = array(
5853 + 'siteurl',
5854 + 'home',
5855 + );
5856 + $cloud_options = self::get_cloud_site_options( $options_to_check );
5857 + $errors = array();
5858 + foreach ( $cloud_options as $cloud_key => $cloud_value ) {
5859 + if ( $cloud_value !== get_option( $cloud_key ) ) {
5860 + $errors[ $cloud_key ] = $cloud_value;
5861 + }
5862 + }
5863 + // Make sure if we're spoofing it, that we don't let the spoof spill over.
5864 + if ( ! isset( $_GET['spoof_identity_crisis'] ) ) {
5865 + set_transient( 'jetpack_has_identity_crisis', $errors, DAY_IN_SECONDS );
5866 + }
5867 + }
5868 + return apply_filters( 'jetpack_has_identity_crisis', $errors, $force_recheck );
5869 + }
5870 +
5871 + /*
5872 + * Displays an admin_notice, alerting the user to an identity crisis.
5873 + */
5874 + public function alert_identity_crisis() {
5875 + if ( ! current_user_can( 'manage_options' ) )
5876 + return;
5877 +
5878 + if ( ! $errors = self::check_identity_crisis() )
5879 + return;
5880 + ?>
5881 +
5882 + <div id="message" class="updated jetpack-message jp-identity-crisis">
5883 + <div class="jetpack-wrap-container">
5884 + <div class="jetpack-text-container">
5885 + <h3><?php _e( 'Something has gotten mixed up!', 'jetpack' ); ?></h3>
5886 + <?php foreach ( $errors as $key => $value ) : ?>
5887 + <p><?php printf( __( 'Your <code>%1$s</code> option is set up as <strong>%2$s</strong>, but your WordPress.com connection lists it as <strong>%3$s</strong>!', 'jetpack' ), $key, (string) get_option( $key ), $value ); ?></p>
5888 + <?php endforeach; ?>
5889 + <p><?php _e( 'This problem can often be resolved by disconnecting, then reconnecting to WordPress.com.', 'jetpack' ); ?> <a href="<?php echo $this->build_reconnect_url() ?>" class="button-connector" id="wpcom-connect"><?php _e( 'Disconnect and Reconnect to WordPress.com', 'jetpack' ); ?></a></p>
5890 + </div>
5891 + </div>
5892 + </div>
5893 +
5894 + <?php
5895 + }
5896 +}
5897
5898 diff --git a/plugins/jetpack/languages/jetpack-uk.mo b/plugins/jetpack/languages/jetpack-uk.mo
5899 new file mode 100644
5900 index 0000000..e1c6c29
5901 Binary files /dev/null and b/plugins/jetpack/languages/jetpack-uk.mo differ
5902
5903 diff --git a/plugins/jetpack/modules/contact-form/css/menu-alter.css b/plugins/jetpack/modules/contact-form/css/menu-alter.css
5904 new file mode 100644
5905 index 0000000..d0b175e
5906 --- /dev/null
5907 +++ b/plugins/jetpack/modules/contact-form/css/menu-alter.css
5908 @@ -0,0 +1,56 @@
5909 +#menu-posts-feedback .wp-menu-image img {
5910 + display: none;
5911 +}
5912 +
5913 +#adminmenu .menu-icon-feedback:hover div.wp-menu-image,
5914 +#adminmenu .menu-icon-feedback.wp-has-current-submenu div.wp-menu-image,
5915 +#adminmenu .menu-icon-feedback.current div.wp-menu-image {
5916 + background: url(../images/grunion-menu-hover.png) no-repeat 7px 7px !important;
5917 +}
5918 +
5919 +#adminmenu .menu-icon-feedback div.wp-menu-image {
5920 + background: url(../images/grunion-menu.png) no-repeat 7px 7px !important;
5921 +}
5922 +
5923 +body.admin-color-mp6 #adminmenu .menu-icon-feedback div.wp-menu-image {
5924 + background: none !important;
5925 +}
5926 +
5927 +body.admin-color-mp6 #adminmenu .menu-icon-feedback div.wp-menu-image:before {
5928 + content: '\f175';
5929 + margin-left: -1px;
5930 +}
5931 +
5932 +.jetpack-contact-form-icon {
5933 + background: url(../images/grunion-form.png) no-repeat;
5934 + width: 16px;
5935 + height: 16px;
5936 + display: inline-block;
5937 + vertical-align: middle;
5938 +}
5939 +
5940 +@media only screen and (-moz-min-device-pixel-ratio: 1.5),
5941 + only screen and (-o-min-device-pixel-ratio: 3/2),
5942 + only screen and (-webkit-min-device-pixel-ratio: 1.5),
5943 + only screen and (min-device-pixel-ratio: 1.5) {
5944 +
5945 + #adminmenu .menu-icon-feedback:hover div.wp-menu-image,
5946 + #adminmenu .menu-icon-feedback.wp-has-current-submenu div.wp-menu-image,
5947 + #adminmenu .menu-icon-feedback.current div.wp-menu-image {
5948 + background: url(../images/grunion-menu-hover-2x.png) no-repeat 7px 7px !important;
5949 + background-size: 15px 16px !important;
5950 + }
5951 +
5952 + #adminmenu .menu-icon-feedback div.wp-menu-image {
5953 + background: url(../images/grunion-menu-2x.png) no-repeat 7px 7px !important;
5954 + background-size: 15px 16px !important;
5955 + }
5956 +
5957 + .jetpack-contact-form-icon {
5958 + background-image: url(../images/grunion-form-2x.png);
5959 + background-size: 13px 12px !important;
5960 + vertical-align: bottom;
5961 + }
5962 +
5963 +}
5964 +
5965
5966 diff --git a/plugins/jetpack/modules/contact-form/css/rtl/grunion-rtl.css b/plugins/jetpack/modules/contact-form/css/rtl/grunion-rtl.css
5967 new file mode 100644
5968 index 0000000..5b1ae1b
5969 --- /dev/null
5970 +++ b/plugins/jetpack/modules/contact-form/css/rtl/grunion-rtl.css
5971 @@ -0,0 +1,12 @@
5972 +/* This file was automatically generated on Feb 27 2013 21:33:34 */
5973 +
5974 +.contact-form .clear-form { clear: both; }
5975 +.contact-form input[type='text'], .contact-form input[type='email'] { width: 300px; max-width: 98%; margin-bottom: 13px; }
5976 +.contact-form select { margin-bottom: 13px; }
5977 +.contact-form textarea { height: 200px; width: 80%; float: none; margin-bottom: 13px; }
5978 +.contact-form input[type='radio'], .contact-form input[type='checkbox'] { float: none; margin-bottom: 13px; }
5979 +.contact-form label { margin-bottom: 3px; float: none; font-weight: bold; display: block; }
5980 +.contact-form label.checkbox, .contact-form label.radio { margin-bottom: 3px; float: none; font-weight: bold; display: inline-block; }
5981 +.contact-form label span { color: #AAA; margin-right: 4px; font-weight: normal; }
5982 +.form-errors .form-error-message { color: red; }
5983 +.textwidget input[type='text'], .textwidget input[type='email'], .textwidget textarea { width: 250px; max-width: 98%; }
5984
5985 diff --git a/plugins/jetpack/modules/contact-form/css/rtl/menu-alter-rtl.css b/plugins/jetpack/modules/contact-form/css/rtl/menu-alter-rtl.css
5986 new file mode 100644
5987 index 0000000..fe82400
5988 --- /dev/null
5989 +++ b/plugins/jetpack/modules/contact-form/css/rtl/menu-alter-rtl.css
5990 @@ -0,0 +1,62 @@
5991 +/* This file was automatically generated on Jun 19 2013 15:20:57 */
5992 +
5993 +#menu-posts-feedback .wp-menu-image img {
5994 + display: none;
5995 +}
5996 +
5997 +#adminmenu .menu-icon-feedback:hover div.wp-menu-image,
5998 +#adminmenu .menu-icon-feedback.wp-has-current-submenu div.wp-menu-image,
5999 +#adminmenu .menu-icon-feedback.current div.wp-menu-image {
6000 + background: url(../../images/grunion-menu-hover.png) no-repeat 7px 7px !important;
6001 +}
6002 +
6003 +#adminmenu .menu-icon-feedback div.wp-menu-image {
6004 + background: url(../../images/grunion-menu.png) no-repeat 7px 7px !important;
6005 +}
6006 +
6007 +body.admin-color-mp6 #adminmenu .toplevel_page_feedback div.wp-menu-image img {
6008 + display: none;
6009 +}
6010 +
6011 +body.admin-color-mp6 #adminmenu .menu-icon-feedback div.wp-menu-image, body.admin-color-mp6 #adminmenu .toplevel_page_feedback div.wp-menu-image {
6012 + background: none !important;
6013 +}
6014 +
6015 +body.admin-color-mp6 #adminmenu .menu-icon-feedback div.wp-menu-image:before, body.admin-color-mp6 #adminmenu .toplevel_page_feedback div.wp-menu-image:before {
6016 + content: '\f175';
6017 + margin-right: -1px;
6018 +}
6019 +
6020 +.jetpack-contact-form-icon {
6021 + background: url(../../images/grunion-form.png) no-repeat;
6022 + width: 16px;
6023 + height: 16px;
6024 + display: inline-block;
6025 + vertical-align: middle;
6026 +}
6027 +
6028 +@media only screen and (-moz-min-device-pixel-ratio: 1.5),
6029 + only screen and (-o-min-device-pixel-ratio: 3/2),
6030 + only screen and (-webkit-min-device-pixel-ratio: 1.5),
6031 + only screen and (min-device-pixel-ratio: 1.5) {
6032 +
6033 + #adminmenu .menu-icon-feedback:hover div.wp-menu-image,
6034 + #adminmenu .menu-icon-feedback.wp-has-current-submenu div.wp-menu-image,
6035 + #adminmenu .menu-icon-feedback.current div.wp-menu-image {
6036 + background: url(../../images/grunion-menu-hover-2x.png) no-repeat 7px 7px !important;
6037 + background-size: 15px 16px !important;
6038 + }
6039 +
6040 + #adminmenu .menu-icon-feedback div.wp-menu-image {
6041 + background: url(../../images/grunion-menu-2x.png) no-repeat 7px 7px !important;
6042 + background-size: 15px 16px !important;
6043 + }
6044 +
6045 + .jetpack-contact-form-icon {
6046 + background-image: url(../../images/grunion-form-2x.png);
6047 + background-size: 13px 12px !important;
6048 + vertical-align: bottom;
6049 + }
6050 +
6051 +}
6052 +
6053
6054 diff --git a/plugins/jetpack/modules/contact-form/grunion-omnisearch.php b/plugins/jetpack/modules/contact-form/grunion-omnisearch.php
6055 new file mode 100644
6056 index 0000000..1622115
6057 --- /dev/null
6058 +++ b/plugins/jetpack/modules/contact-form/grunion-omnisearch.php
6059 @@ -0,0 +1,65 @@
6060 +<?php
6061 +
6062 +if( ! class_exists( 'WP_List_Table' ) )
6063 + require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
6064 +
6065 +class Jetpack_Omnisearch_Grunion extends WP_List_Table {
6066 + static $instance;
6067 + var $post_type = 'feedback';
6068 +
6069 + function __construct() {
6070 + self::$instance = $this;
6071 + add_filter( 'omnisearch_results', array( $this, 'search'), 12, 2 );
6072 + }
6073 +
6074 + function search( $results, $search_term ) {
6075 + parent::__construct();
6076 +
6077 + $this->post_type_obj = get_post_type_object( $this->post_type );
6078 +
6079 + $search_url = esc_url( admin_url( sprintf( 'edit.php?post_type=%s&s=%s', urlencode( $this->post_type_obj->name ), urlencode( $search_term ) ) ) );
6080 + $search_link = sprintf( ' <a href="%s" class="add-new-h2">%s</a>', $search_url, esc_html( $this->post_type_obj->labels->search_items ) );
6081 + $html = '<h2>' . esc_html( $this->post_type_obj->labels->name ) . $search_link .'</h2>';
6082 +
6083 + $this->prepare_items( $search_term );
6084 +
6085 + ob_start();
6086 + $this->display();
6087 + $html .= ob_get_clean();
6088 +
6089 + $results[ $this->post_type_obj->labels->name ] = $html;
6090 + return $results;
6091 + }
6092 +
6093 + function get_columns() {
6094 + $columns = array(
6095 + 'feedback_from' => __('From', 'jetpack'),
6096 + 'feedback_message' => __('Message', 'jetpack'),
6097 + 'feedback_date' => __('Date', 'jetpack'),
6098 + );
6099 + return $columns;
6100 + }
6101 +
6102 + function prepare_items( $search_term = '' ) {
6103 + $this->_column_headers = array( $this->get_columns(), array(), array() );
6104 + $num_results = apply_filters( 'omnisearch_num_results', 5 );
6105 + $this->items = get_posts( array(
6106 + 's' => $search_term,
6107 + 'post_type' => $this->post_type,
6108 + 'posts_per_page' => $num_results,
6109 + ) );
6110 + }
6111 +
6112 + function column_default( $post, $column_name ) {
6113 + switch ( $column_name ) {
6114 + case 'feedback_from':
6115 + case 'feedback_message':
6116 + case 'feedback_date':
6117 + ob_start();
6118 + grunion_manage_post_columns( $column_name, $post->ID );
6119 + return ob_get_clean();
6120 + default:
6121 + return '<pre>' . print_r( $post, true ) . '</pre>';
6122 + }
6123 + }
6124 +}
6125
6126 diff --git a/plugins/jetpack/modules/contact-form/js/grunion-frontend.js b/plugins/jetpack/modules/contact-form/js/grunion-frontend.js
6127 new file mode 100644
6128 index 0000000..c87c164
6129 --- /dev/null
6130 +++ b/plugins/jetpack/modules/contact-form/js/grunion-frontend.js
6131 @@ -0,0 +1,3 @@
6132 +jQuery( function ( $ ) {
6133 + $( '.contact-form input[type="date"]' ).datepicker( { dateFormat : 'yy-mm-dd' } );
6134 +} );
6135 \ No newline at end of file
6136
6137 diff --git a/plugins/jetpack/modules/custom-css/custom-css/css/ace.css b/plugins/jetpack/modules/custom-css/custom-css/css/ace.css
6138 new file mode 100644
6139 index 0000000..e941893
6140 --- /dev/null
6141 +++ b/plugins/jetpack/modules/custom-css/custom-css/css/ace.css
6142 @@ -0,0 +1,25 @@
6143 +#safecss-container {
6144 + position: relative;
6145 + width: 99.5%;
6146 + height: 400px;
6147 + border: 1px solid #dfdfdf;
6148 + border-radius: 3px;
6149 +}
6150 +
6151 +#safecss, #safecss-container .ace_editor, #safecss-container .ace_editor * {
6152 + font-family: Consolas, Monaco, Courier, monospace !important;
6153 +}
6154 +
6155 +#safecss-ace {
6156 + width: 100%;
6157 + height: 100%;
6158 + display: none; /* Hide on load otherwise it looks weird */
6159 +}
6160 +
6161 +#safecss-ace.ace_editor {
6162 + display: block;
6163 +}
6164 +
6165 +#safecss-container .ace-tm .ace_gutter {
6166 + background-color: #ededed;
6167 +}
6168
6169 diff --git a/plugins/jetpack/modules/custom-css/custom-css/css/css-editor.css b/plugins/jetpack/modules/custom-css/custom-css/css/css-editor.css
6170 new file mode 100644
6171 index 0000000..4dec412
6172 --- /dev/null
6173 +++ b/plugins/jetpack/modules/custom-css/custom-css/css/css-editor.css
6174 @@ -0,0 +1,24 @@
6175 +#revision-field-post_title, #revision-field-post_excerpt {
6176 + display: none;
6177 +}
6178 +
6179 +#safecssform {
6180 + position: relative;
6181 +}
6182 +
6183 +#poststuff {
6184 + padding-top: 0;
6185 +}
6186 +
6187 +#safecss {
6188 + min-height: 250px;
6189 + width: 100%;
6190 +}
6191 +
6192 +.misc-pub-section > span {
6193 + font-weight: bold;
6194 +}
6195 +
6196 +.misc-pub-section > div {
6197 + margin-top: 3px;
6198 +}
6199 \ No newline at end of file
6200
6201 diff --git a/plugins/jetpack/modules/custom-css/custom-css/js/ace/mode-less.js b/plugins/jetpack/modules/custom-css/custom-css/js/ace/mode-less.js
6202 new file mode 100644
6203 index 0000000..68b4ca7
6204 --- /dev/null
6205 +++ b/plugins/jetpack/modules/custom-css/custom-css/js/ace/mode-less.js
6206 @@ -0,0 +1 @@
6207 +ace.define("ace/mode/less",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/less_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./less_highlight_rules").LessHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("./folding/cstyle").FoldMode,f=function(){this.$tokenizer=new s((new o).getRules(),"i"),this.$outdent=new u,this.foldingRules=new a};r.inherits(f,i),function(){this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e).tokens;if(i.length&&i[i.length-1].type=="comment")return r;var s=t.match(/^.*\{\s*$/);return s&&(r+=n),r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)}}.call(f.prototype),t.Mode=f}),ace.define("ace/mode/less_highlight_rules",["require","exports","module"
6208 ,"ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e=i.arrayToMap(function(){var e="-webkit-|-moz-|-o-|-ms-|-svg-|-pie-|-khtml-".split("|"),t="appearance|background-clip|background-inline-policy|background-origin|background-size|binding|border-bottom-colors|border-left-colors|border-right-colors|border-top-colors|border-end|border-end-color|border-end-style|border-end-width|border-image|border-start|border-start-color|border-start-style|border-start-width|box-align|box-direction|box-flex|box-flexgroup|box-ordinal-group|box-orient|box-pack|box-sizing|column-count|column-gap|column-width|column-rule|column-rule-width|column-rule-style|column-rule-color|float-edge|font-feature-settings|font-language-override|force-broken-image-icon|image-region|margin-end|margin-start|opacity|outline|outline-color|outline-offset|outline-radius|outline-radius-bottomleft|
6209 outline-radius-bottomright|outline-radius-topleft|outline-radius-topright|outline-style|outline-width|padding-end|padding-start|stack-sizing|tab-size|text-blink|text-decoration-color|text-decoration-line|text-decoration-style|transform|transform-origin|transition|transition-delay|transition-duration|transition-property|transition-timing-function|user-focus|user-input|user-modify|user-select|window-shadow|border-radius".split("|"),n="azimuth|background-attachment|background-color|background-image|background-position|background-repeat|background|border-bottom-color|border-bottom-style|border-bottom-width|border-bottom|border-collapse|border-color|border-left-color|border-left-style|border-left-width|border-left|border-right-color|border-right-style|border-right-width|border-right|border-spacing|border-style|border-top-color|border-top-style|border-top-width|border-top|border-width|border|bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|counter-reset|cue-after|
6210 cue-before|cue|cursor|direction|display|elevation|empty-cells|float|font-family|font-size-adjust|font-size|font-stretch|font-style|font-variant|font-weight|font|height|left|letter-spacing|line-height|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|marker-offset|margin|marks|max-height|max-width|min-height|min-width|opacity|orphans|outline-color|outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page|pause-after|pause-before|pause|pitch-range|pitch|play-during|position|quotes|richness|right|size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|stress|table-layout|text-align|text-decoration|text-indent|text-shadow|text-transform|top|unicode-bidi|vertical-align|visibility|voice-family|volume|white-space|widows|width|word-spacing|z-index".split("|"),r=[];for(var i=0,s=e.length;i<
6211 s;i++)Array.prototype.push.apply(r,(e[i]+t.join("|"+e[i])).split("|"));return Array.prototype.push.apply(r,t),Array.prototype.push.apply(r,n),r}()),t=i.arrayToMap("hsl|hsla|rgb|rgba|url|attr|counter|counters|lighten|darken|saturate|desaturate|fadein|fadeout|fade|spin|mix|hue|saturation|lightness|alpha|round|ceil|floor|percentage|color|iscolor|isnumber|isstring|iskeyword|isurl|ispixel|ispercentage|isem".split("|")),n=i.arrayToMap("absolute|all-scroll|always|armenian|auto|baseline|below|bidi-override|block|bold|bolder|border-box|both|bottom|break-all|break-word|capitalize|center|char|circle|cjk-ideographic|col-resize|collapse|content-box|crosshair|dashed|decimal-leading-zero|decimal|default|disabled|disc|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ellipsis|fixed|georgian|groove|hand|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|inactive|inherit|inline-block|inl
6212 ine|inset|inside|inter-ideograph|inter-word|italic|justify|katakana-iroha|katakana|keep-all|left|lighter|line-edge|line-through|line|list-item|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|medium|middle|move|n-resize|ne-resize|newspaper|no-drop|no-repeat|nw-resize|none|normal|not-allowed|nowrap|oblique|outset|outside|overline|pointer|progress|relative|repeat-x|repeat-y|repeat|right|ridge|row-resize|rtl|s-resize|scroll|se-resize|separate|small-caps|solid|square|static|strict|super|sw-resize|table-footer-group|table-header-group|tb-rl|text-bottom|text-top|text|thick|thin|top|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|zero".split("|")),r=i.arrayToMap("aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow".split("|")),s=i.arrayToMap("@mixin|@extend|@include|@import|@media|@debug|@warn|@if|@for|@each|@while|@else|@font-fac
6213 e|@-webkit-keyframes|if|and|!default|module|def|end|declare|when|not|and".split("|")),o=i.arrayToMap("a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdo|big|blockquote|body|br|button|canvas|caption|center|cite|code|col|colgroup|command|datalist|dd|del|details|dfn|dir|div|dl|dt|em|embed|fieldset|figcaption|figure|font|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|header|hgroup|hr|html|i|iframe|img|input|ins|keygen|kbd|label|legend|li|link|map|mark|menu|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|rp|rt|ruby|s|samp|script|section|select|small|source|span|strike|strong|style|sub|summary|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|u|ul|var|video|wbr|xmp".split("|")),u="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))";this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},{token:"comment",merge:!0,regex:"\\/\\*",next:"comment"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:
6214 "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:u+"(?:em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)"},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:"constant.numeric",regex:u},{token:function(e){return s.hasOwnProperty(e)?"keyword":"variable"},regex:"@[a-z0-9_\\-@]*\\b"},{token:function(i){return e.hasOwnProperty(i.toLowerCase())?"support.type":s.hasOwnProperty(i)?"keyword":n.hasOwnProperty(i)?"constant.language":t.hasOwnProperty(i)?"support.function":r.hasOwnProperty(i.toLowerCase())?"support.constant.color":o.hasOwnProperty(i.toLowerCase())?"variable.language":"text"},regex:"\\-?[@a-z_][@a-z0-9_\\-]*"},{token:"variable.language",regex:"#[a-z0-9-_]+"},{token:"variable.language",regex:"\\.[a-z0-9-_]+"},{token:"variable.language",regex:":[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"},{token:"keyword.operator",regex:"<|>|<=|>=|==|!=|-|%|#|\\+|\\$|\\+|\\*"},{token:"paren.lparen",regex:"[[({]"},{t
6215 oken:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",merge:!0,regex:".+"}]}};r.inherits(o,s),t.LessHighlightRules=o}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fol
6216 d_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)})
6217 \ No newline at end of file
6218
6219 diff --git a/plugins/jetpack/modules/custom-css/custom-css/js/ace/mode-scss.js b/plugins/jetpack/modules/custom-css/custom-css/js/ace/mode-scss.js
6220 new file mode 100644
6221 index 0000000..eca0160
6222 --- /dev/null
6223 +++ b/plugins/jetpack/modules/custom-css/custom-css/js/ace/mode-scss.js
6224 @@ -0,0 +1 @@
6225 +ace.define("ace/mode/scss",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/scss_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/folding/cstyle"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./scss_highlight_rules").ScssHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("./folding/cstyle").FoldMode,f=function(){this.$tokenizer=new s((new o).getRules(),"i"),this.$outdent=new u,this.foldingRules=new a};r.inherits(f,i),function(){this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t),i=this.$tokenizer.getLineTokens(t,e).tokens;if(i.length&&i[i.length-1].type=="comment")return r;var s=t.match(/^.*\{\s*$/);return s&&(r+=n),r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)}}.call(f.prototype),t.Mode=f}),ace.define("ace/mode/scss_highlight_rules",["require","exports","module"
6226 ,"ace/lib/oop","ace/lib/lang","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/lang"),s=e("./text_highlight_rules").TextHighlightRules,o=function(){var e=i.arrayToMap(function(){var e="-webkit-|-moz-|-o-|-ms-|-svg-|-pie-|-khtml-".split("|"),t="appearance|background-clip|background-inline-policy|background-origin|background-size|binding|border-bottom-colors|border-left-colors|border-right-colors|border-top-colors|border-end|border-end-color|border-end-style|border-end-width|border-image|border-start|border-start-color|border-start-style|border-start-width|box-align|box-direction|box-flex|box-flexgroup|box-ordinal-group|box-orient|box-pack|box-sizing|column-count|column-gap|column-width|column-rule|column-rule-width|column-rule-style|column-rule-color|float-edge|font-feature-settings|font-language-override|force-broken-image-icon|image-region|margin-end|margin-start|opacity|outline|outline-color|outline-offset|outline-radius|outline-radius-bottomleft|
6227 outline-radius-bottomright|outline-radius-topleft|outline-radius-topright|outline-style|outline-width|padding-end|padding-start|stack-sizing|tab-size|text-blink|text-decoration-color|text-decoration-line|text-decoration-style|transform|transform-origin|transition|transition-delay|transition-duration|transition-property|transition-timing-function|user-focus|user-input|user-modify|user-select|window-shadow|border-radius".split("|"),n="azimuth|background-attachment|background-color|background-image|background-position|background-repeat|background|border-bottom-color|border-bottom-style|border-bottom-width|border-bottom|border-collapse|border-color|border-left-color|border-left-style|border-left-width|border-left|border-right-color|border-right-style|border-right-width|border-right|border-spacing|border-style|border-top-color|border-top-style|border-top-width|border-top|border-width|border|bottom|box-sizing|caption-side|clear|clip|color|content|counter-increment|counter-reset|cue-after|
6228 cue-before|cue|cursor|direction|display|elevation|empty-cells|float|font-family|font-size-adjust|font-size|font-stretch|font-style|font-variant|font-weight|font|height|left|letter-spacing|line-height|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|marker-offset|margin|marks|max-height|max-width|min-height|min-width|opacity|orphans|outline-color|outline-style|outline-width|outline|overflow|overflow-x|overflow-y|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page|pause-after|pause-before|pause|pitch-range|pitch|play-during|position|quotes|richness|right|size|speak-header|speak-numeral|speak-punctuation|speech-rate|speak|stress|table-layout|text-align|text-decoration|text-indent|text-shadow|text-transform|top|unicode-bidi|vertical-align|visibility|voice-family|volume|white-space|widows|width|word-spacing|z-index".split("|"),r=[];for(var i=0,s=e.length;i<
6229 s;i++)Array.prototype.push.apply(r,(e[i]+t.join("|"+e[i])).split("|"));return Array.prototype.push.apply(r,t),Array.prototype.push.apply(r,n),r}()),t=i.arrayToMap("hsl|hsla|rgb|rgba|url|attr|counter|counters|abs|adjust_color|adjust_hue|alpha|join|blue|ceil|change_color|comparable|complement|darken|desaturate|floor|grayscale|green|hue|if|invert|join|length|lighten|lightness|mix|nth|opacify|opacity|percentage|quote|red|round|saturate|saturation|scale_color|transparentize|type_of|unit|unitless|unqoute".split("|")),n=i.arrayToMap("absolute|all-scroll|always|armenian|auto|baseline|below|bidi-override|block|bold|bolder|border-box|both|bottom|break-all|break-word|capitalize|center|char|circle|cjk-ideographic|col-resize|collapse|content-box|crosshair|dashed|decimal-leading-zero|decimal|default|disabled|disc|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ellipsis|fixed|georgian|groove|hand|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|ideogr
6230 aph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|inactive|inherit|inline-block|inline|inset|inside|inter-ideograph|inter-word|italic|justify|katakana-iroha|katakana|keep-all|left|lighter|line-edge|line-through|line|list-item|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|medium|middle|move|n-resize|ne-resize|newspaper|no-drop|no-repeat|nw-resize|none|normal|not-allowed|nowrap|oblique|outset|outside|overline|pointer|progress|relative|repeat-x|repeat-y|repeat|right|ridge|row-resize|rtl|s-resize|scroll|se-resize|separate|small-caps|solid|square|static|strict|super|sw-resize|table-footer-group|table-header-group|tb-rl|text-bottom|text-top|text|thick|thin|top|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|zero".split("|")),r=i.arrayToMap("aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow".split("|")),s=i.ar
6231 rayToMap("@mixin|@extend|@include|@import|@media|@debug|@warn|@if|@for|@each|@while|@else|@font-face|@-webkit-keyframes|if|and|!default|module|def|end|declare".split("|")),o=i.arrayToMap("a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdo|big|blockquote|body|br|button|canvas|caption|center|cite|code|col|colgroup|command|datalist|dd|del|details|dfn|dir|div|dl|dt|em|embed|fieldset|figcaption|figure|font|footer|form|frame|frameset|h1|h2|h3|h4|h5|h6|head|header|hgroup|hr|html|i|iframe|img|input|ins|keygen|kbd|label|legend|li|link|map|mark|menu|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|rp|rt|ruby|s|samp|script|section|select|small|source|span|strike|strong|style|sub|summary|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|u|ul|var|video|wbr|xmp".split("|")),u="\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))";this.$rules={start:[{token:"comment",regex:"\\/\\/.*$"},{token:"comment",merge:!0,regex:"\\/\\*",next:"commen
6232 t"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",merge:!0,regex:'["].*\\\\$',next:"qqstring"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"string",merge:!0,regex:"['].*\\\\$",next:"qstring"},{token:"constant.numeric",regex:u+"(?:em|ex|px|cm|mm|in|pt|pc|deg|rad|grad|ms|s|hz|khz|%)"},{token:"constant.numeric",regex:"#[a-f0-9]{6}"},{token:"constant.numeric",regex:"#[a-f0-9]{3}"},{token:"constant.numeric",regex:u},{token:function(i){return e.hasOwnProperty(i.toLowerCase())?"support.type":s.hasOwnProperty(i)?"keyword":n.hasOwnProperty(i)?"constant.language":t.hasOwnProperty(i)?"support.function":r.hasOwnProperty(i.toLowerCase())?"support.constant.color":o.hasOwnProperty(i.toLowerCase())?"variable.language":"text"},regex:"\\-?[@a-z_][@a-z0-9_\\-]*"},{token:"variable",regex:"[a-z_\\-$][a-z0-9_\\-$]*\\b"},{token:"variable.language",regex:"#[a-z0-9-_]+"},{token:"variable.language",regex:"\\.[a-z0-9-_]+"},{token:"variable.language",regex:"
6233 :[a-z0-9-_]+"},{token:"constant",regex:"[a-z0-9-_]+"},{token:"keyword.operator",regex:"<|>|<=|>=|==|!=|-|%|#|\\+|\\$|\\+|\\*"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],comment:[{token:"comment",regex:".*?\\*\\/",next:"start"},{token:"comment",merge:!0,regex:".+"}],qqstring:[{token:"string",regex:'(?:(?:\\\\.)|(?:[^"\\\\]))*?"',next:"start"},{token:"string",merge:!0,regex:".+"}],qstring:[{token:"string",regex:"(?:(?:\\\\.)|(?:[^'\\\\]))*?'",next:"start"},{token:"string",merge:!0,regex:".+"}]}};r.inherits(o,s),t.ScssHighlightRules=o}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t
6234 )return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)})
6235 \ No newline at end of file
6236
6237 diff --git a/plugins/jetpack/modules/custom-css/custom-css/js/css-editor.js b/plugins/jetpack/modules/custom-css/custom-css/js/css-editor.js
6238 new file mode 100644
6239 index 0000000..6d4f082
6240 --- /dev/null
6241 +++ b/plugins/jetpack/modules/custom-css/custom-css/js/css-editor.js
6242 @@ -0,0 +1,81 @@
6243 +( function ( $ ) {
6244 + var safe, win, safecssResize, safecssInit;
6245 +
6246 + safecssResize = function () {
6247 + safe.height( win.height() - safe.offset().top - 250 );
6248 + };
6249 +
6250 + safecssInit = function() {
6251 + safe = $( '#safecss' );
6252 + win = $( window );
6253 +
6254 + postboxes.add_postbox_toggles( 'editcss' );
6255 + safecssResize();
6256 +
6257 + // Bound on a parent to ensure that this click event executes last.
6258 + $( '#safecssform' ).on( 'click', '#preview', function ( e ) {
6259 + e.preventDefault();
6260 +
6261 + document.forms["safecssform"].target = "csspreview";
6262 + document.forms["safecssform"].action.value = 'preview';
6263 + document.forms["safecssform"].submit();
6264 + document.forms["safecssform"].target = "";
6265 + document.forms["safecssform"].action.value = 'save';
6266 + } );
6267 + };
6268 +
6269 + window.onresize = safecssResize;
6270 + addLoadEvent( safecssInit );
6271 +} )( jQuery );
6272 +
6273 +jQuery( function ( $ ) {
6274 + $( '.edit-preprocessor' ).bind( 'click', function ( e ) {
6275 + e.preventDefault();
6276 +
6277 + $( '#preprocessor-select' ).slideDown();
6278 + $( this ).hide();
6279 + } );
6280 +
6281 + $( '.cancel-preprocessor' ).bind( 'click', function ( e ) {
6282 + e.preventDefault();
6283 +
6284 + $( '#preprocessor-select' ).slideUp( function () {
6285 + $( '.edit-preprocessor' ).show();
6286 + $( '#preprocessor_choices' ).val( $( '#custom_css_preprocessor' ).val() );
6287 + } );
6288 + } );
6289 +
6290 + $( '.save-preprocessor' ).bind( 'click', function ( e ) {
6291 + e.preventDefault();
6292 +
6293 + $( '#preprocessor-select' ).slideUp();
6294 + $( '#preprocessor-display' ).text( $( '#preprocessor_choices option:selected' ).text() );
6295 + $( '#custom_css_preprocessor' ).val( $( '#preprocessor_choices' ).val() ).change();
6296 + $( '.edit-preprocessor' ).show();
6297 + } );
6298 +
6299 + $( '.edit-css-mode' ).bind( 'click', function ( e ) {
6300 + e.preventDefault();
6301 +
6302 + $( '#css-mode-select' ).slideDown();
6303 + $( this ).hide();
6304 + } );
6305 +
6306 + $( '.cancel-css-mode' ).bind( 'click', function ( e ) {
6307 + e.preventDefault();
6308 +
6309 + $( '#css-mode-select' ).slideUp( function () {
6310 + $( '.edit-css-mode' ).show();
6311 + $( 'input[name=add_to_existing_display][value=' + $( '#add_to_existing' ).val() + ']' ).attr( 'checked', true );
6312 + } );
6313 + } );
6314 +
6315 + $( '.save-css-mode' ).bind( 'click', function ( e ) {
6316 + e.preventDefault();
6317 +
6318 + $( '#css-mode-select' ).slideUp();
6319 + $( '#css-mode-display' ).text( $( 'input[name=add_to_existing_display]:checked' ).val() == 'true' ? 'Add-on' : 'Replacement' );
6320 + $( '#add_to_existing' ).val( $( 'input[name=add_to_existing_display]:checked' ).val() );
6321 + $( '.edit-css-mode' ).show();
6322 + } );
6323 +} );
6324 \ No newline at end of file
6325
6326 diff --git a/plugins/jetpack/modules/infinite-scroll/themes/twentythirteen.css b/plugins/jetpack/modules/infinite-scroll/themes/twentythirteen.css
6327 new file mode 100644
6328 index 0000000..ba169b3
6329 --- /dev/null
6330 +++ b/plugins/jetpack/modules/infinite-scroll/themes/twentythirteen.css
6331 @@ -0,0 +1,90 @@
6332 +/* =Infinite Scroll
6333 +-------------------------------------------------------------- */
6334 +
6335 +.infinite-wrap {
6336 + border-top: 0;
6337 +}
6338 +
6339 +/* Spinner */
6340 +.infinite-loader {
6341 + background-color: #e8e5ce;
6342 + padding: 40px 0;
6343 +}
6344 +.infinite-loader .spinner {
6345 + margin: 0 auto;
6346 + width: 34px;
6347 + height: 34px;
6348 +}
6349 +.sidebar .infinite-loader .spinner {
6350 + padding-right: 376px;
6351 +}
6352 +.rtl.sidebar .infinite-loader .spinner {
6353 + padding-left: 376px;
6354 + padding-right: 0;
6355 +}
6356 +
6357 +/* Click-to-load */
6358 +#infinite-handle {
6359 + background-color: #e8e5ce;
6360 + padding: 40px 0;
6361 + text-align: center;
6362 +}
6363 +.sidebar #infinite-handle {
6364 + padding-right: 376px;
6365 +}
6366 +.rtl.sidebar #infinite-handle {
6367 + padding-left: 376px;
6368 + padding-right: 0;
6369 +}
6370 +#infinite-handle span {
6371 + background: #e05d22; /* Old browsers */
6372 + background: -webkit-linear-gradient(top, #e05d22 0%, #d94412 100%); /* Chrome 10+, Safari 5.1+ */
6373 + background: linear-gradient(to bottom, #e05d22 0%, #d94412 100%); /* W3C */
6374 + border: none;
6375 + border-bottom: 3px solid #b93207;
6376 + border-radius: 2px;
6377 + display: inline-block;
6378 + color: #fff;
6379 + font-size: 100%;
6380 + padding: 11px 24px 10px;
6381 + text-decoration: none;
6382 +}
6383 +#infinite-handle span:hover {
6384 + background: #ed6a31; /* Old browsers */
6385 + background: -webkit-linear-gradient(top, #ed6a31 0%, #e55627 100%); /* Chrome 10+, Safari 5.1+ */
6386 + background: linear-gradient(to bottom, #ed6a31 0%, #e55627 100%); /* W3C */
6387 + outline: none;
6388 +}
6389 +#infinite-handle span:active {
6390 + background: #d94412; /* Old browsers */
6391 + background: -webkit-linear-gradient(top, #d94412 0%, #e05d22 100%); /* Chrome 10+, Safari 5.1+ */
6392 + background: linear-gradient(to bottom, #d94412 0%, #e05d22 100%); /* W3C */
6393 + border: none;
6394 + border-top: 3px solid #b93207;
6395 + padding: 10px 24px 11px;
6396 +}
6397 +
6398 +/* Elements to hide: post navigation, normal footer. */
6399 +.infinite-scroll .paging-navigation,
6400 +.infinite-scroll.neverending #colophon {
6401 + display: none;
6402 +}
6403 +
6404 +/* Hooks to infinity-end body class to restore footer. */
6405 +.infinity-end.neverending #colophon {
6406 + display: block;
6407 +}
6408 +
6409 +/* For small viewports. */
6410 +@media (max-width: 999px) {
6411 + .sidebar .infinite-loader .spinner,
6412 + .rtl.sidebar .infinite-loader .spinner {
6413 + padding-right: 0;
6414 + padding-left: 0;
6415 + }
6416 + .infinite-scroll #infinite-handle,
6417 + .rtl.sidebar #infinite-handle {
6418 + padding-right: 0;
6419 + padding-left: 0;
6420 + }
6421 +}
6422 \ No newline at end of file
6423
6424 diff --git a/plugins/jetpack/modules/infinite-scroll/themes/twentythirteen.php b/plugins/jetpack/modules/infinite-scroll/themes/twentythirteen.php
6425 new file mode 100644
6426 index 0000000..dbc18c7
6427 --- /dev/null
6428 +++ b/plugins/jetpack/modules/infinite-scroll/themes/twentythirteen.php
6429 @@ -0,0 +1,26 @@
6430 +<?php
6431 +/**
6432 + * Infinite Scroll Theme Assets
6433 + *
6434 + * Register support for Twenty Thirteen.
6435 + */
6436 +
6437 +/**
6438 + * Add theme support for infinite scroll
6439 + */
6440 +function twentythirteen_infinite_scroll_init() {
6441 + add_theme_support( 'infinite-scroll', array(
6442 + 'container' => 'content',
6443 + 'footer' => 'page',
6444 + 'footer_widgets' => array( 'sidebar-1' )
6445 + ) );
6446 +}
6447 +add_action( 'after_setup_theme', 'twentythirteen_infinite_scroll_init' );
6448 +
6449 +/**
6450 + * Enqueue CSS stylesheet with theme styles for Infinite Scroll.
6451 + */
6452 +function twentythirteen_infinite_scroll_enqueue_styles() {
6453 + wp_enqueue_style( 'infinity-twentythirteen', plugins_url( 'twentythirteen.css', __FILE__ ), array( 'the-neverending-homepage' ), '20130409' );
6454 +}
6455 +add_action( 'wp_enqueue_scripts', 'twentythirteen_infinite_scroll_enqueue_styles', 25 );
6456 \ No newline at end of file
6457
6458 diff --git a/plugins/jetpack/modules/likes/post-count.js b/plugins/jetpack/modules/likes/post-count.js
6459 new file mode 100644
6460 index 0000000..d93b885
6461 --- /dev/null
6462 +++ b/plugins/jetpack/modules/likes/post-count.js
6463 @@ -0,0 +1,69 @@
6464 +var wpPostLikeCount;
6465 +
6466 +(function($) {
6467 +
6468 + wpPostLikeCount = {
6469 +
6470 + jsonAPIbase: 'https://public-api.wordpress.com/rest/v1',
6471 + APIqueue: [],
6472 +
6473 + wpPostLikeCount: function() {
6474 + $( '.post-like-count' ).each( function() {
6475 + var post_id = $(this).attr( 'data-post-id' );
6476 + var blog_id = $(this).attr( 'data-blog-id' );
6477 + wpPostLikeCount.APIqueue.push( '/sites/' + blog_id + '/posts/' + post_id + '/likes' );
6478 + } );
6479 + wpPostLikeCount.getCounts();
6480 + },
6481 +
6482 + showCount: function( post_id, count ) {
6483 + $( '#post-like-count-' + post_id ).find( '.comment-count' ).hide();
6484 + $( '#post-like-count-' + post_id ).find( '.comment-count' ).text( count );
6485 + $( '#post-like-count-' + post_id ).find( '.comment-count' ).fadeIn();
6486 + },
6487 +
6488 + getCounts: function() {
6489 + var batchRequest = {
6490 + path: '/batch',
6491 + data: '',
6492 + success: function( response ) {
6493 + for ( var path in response ) {
6494 + if ( ! response[path]['error_data'] ) {
6495 + var urlPieces = path.split( '/' ); // pieces[4] = post id;
6496 + var post_id = urlPieces[4];
6497 + wpPostLikeCount.showCount( post_id, response[path].found );
6498 + }
6499 + }
6500 + },
6501 + error: function( response ) {
6502 + }
6503 + };
6504 +
6505 + var amp = '';
6506 + for( var i = 0; i < wpPostLikeCount.APIqueue.length; i++ ) {
6507 + if ( i > 0 )
6508 + amp = '&';
6509 + batchRequest.data += amp + 'urls[]=' + wpPostLikeCount.APIqueue[i];
6510 + }
6511 +
6512 + wpPostLikeCount.request( batchRequest );
6513 + },
6514 +
6515 + request: function( options ) {
6516 + return $.ajax( {
6517 + type: 'GET',
6518 + url: wpPostLikeCount.jsonAPIbase + options.path,
6519 + dataType : "jsonp",
6520 + data: options.data,
6521 + success: function( response ) { options.success( response ) },
6522 + error: function( response ) { options.error( response ) }
6523 + } )
6524 + }
6525 +
6526 + };
6527 +
6528 +})(jQuery);
6529 +
6530 +jQuery(document).ready(function($) {
6531 + wpPostLikeCount.wpPostLikeCount();
6532 +});
6533 \ No newline at end of file
6534
6535 diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.eot b/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.eot
6536 new file mode 100644
6537 index 0000000..5a60506
6538 Binary files /dev/null and b/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.eot differ
6539
6540 diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.svg b/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.svg
6541 new file mode 100644
6542 index 0000000..3dce209
6543 --- /dev/null
6544 +++ b/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.svg
6545 @@ -0,0 +1,81 @@
6546 +<?xml version="1.0" standalone="no"?>
6547 +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
6548 +<svg xmlns="http://www.w3.org/2000/svg">
6549 +<metadata></metadata>
6550 +<defs>
6551 +<font id="genericonsregular" horiz-adv-x="2048" >
6552 +<font-face units-per-em="2048" ascent="1638" descent="-410" />
6553 +<missing-glyph horiz-adv-x="500" />
6554 +<glyph unicode="&#x2000;" horiz-adv-x="1024" />
6555 +<glyph unicode="&#x2001;" />
6556 +<glyph unicode="&#x2002;" horiz-adv-x="1024" />
6557 +<glyph unicode="&#x2003;" />
6558 +<glyph unicode="&#x2004;" horiz-adv-x="682" />
6559 +<glyph unicode="&#x2005;" horiz-adv-x="512" />
6560 +<glyph unicode="&#x2006;" horiz-adv-x="341" />
6561 +<glyph unicode="&#x2007;" horiz-adv-x="341" />
6562 +<glyph unicode="&#x2008;" horiz-adv-x="256" />
6563 +<glyph unicode="&#x2009;" horiz-adv-x="409" />
6564 +<glyph unicode="&#x200a;" horiz-adv-x="113" />
6565 +<glyph unicode="&#x202f;" horiz-adv-x="409" />
6566 +<glyph unicode="&#x205f;" horiz-adv-x="512" />
6567 +<glyph unicode="&#xe000;" horiz-adv-x="500" d="M0 0z" />
6568 +<glyph unicode="&#xf100;" d="M512 512v128h768v-128h-768zM512 768v128h256v-128h-256zM512 1024v128h640v-128h-640zM512 1280v128h1024v-128h-1024zM896 768v128h640v-128h-640zM1280 1024v128h256v-128h-256z" />
6569 +<glyph unicode="&#xf101;" d="M256 1024q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5zM768 1024q0 -106 75 -181t181 -75t181 75t75 181t-75 181t-181 75t-181 -75t-75 -181z" />
6570 +<glyph unicode="&#xf102;" d="M128 384v896l512 128l128 256h512l128 -256h512v-1024h-1792zM256 1440v160h256v-96zM576 960q0 -185 131.5 -316.5t316.5 -131.5q186 0 317 131.5t131 316.5t-131 316.5t-317 131.5q-185 0 -316.5 -131.5t-131.5 -316.5zM704 960q0 133 93.5 226.5t226.5 93.5 t226.5 -93.5t93.5 -226.5t-93.5 -226.5t-226.5 -93.5t-226.5 93.5t-93.5 226.5z" />
6571 +<glyph unicode="&#xf103;" d="M128 512v384h384v-384h-384zM128 1024v384h896v-384h-896zM640 512v384h384v-384h-384zM1152 512v896h896v-896h-896z" />
6572 +<glyph unicode="&#xf104;" d="M512 384v1280l1152 -640z" />
6573 +<glyph unicode="&#xf105;" d="M640 1408q0 159 112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5q0 -124 -71.5 -222t-184.5 -138v-536l-256 -128v664q-113 40 -184.5 138t-71.5 222z" />
6574 +<glyph unicode="&#xf106;" d="M384 640l128 768h512l-256 -768h-384zM1152 640l128 768h512l-256 -768h-384z" />
6575 +<glyph unicode="&#xf107;" d="M376 852q0 108 72 204l160 128l96 -96l-160 -128q-48 -96 0 -192l96 -96q96 -48 192 0l128 160l96 -96l-128 -160q-96 -72 -204 -72t-180 72l-96 96q-72 72 -72 180zM736 960l352 352l96 -96l-352 -352zM864 1440l128 160q96 72 204 72t180 -72l96 -96q72 -72 72 -180 t-72 -204l-160 -128l-96 96l160 128q48 96 0 192l-96 96q-96 48 -192 0l-128 -160z" />
6576 +<glyph unicode="&#xf108;" d="M0 1152v384q0 96 80 176t176 80h1024q96 0 176 -80t80 -176v-384q0 -96 -80 -176t-176 -80h-448l-448 -448v448h-128q-96 0 -176 80t-80 176zM768 640l128 128h384q168 0 276 108t108 276v384q96 0 176 -80t80 -176v-384q0 -96 -80 -176t-176 -80h-128v-448l-448 448 h-320z" />
6577 +<glyph unicode="&#xf109;" d="M256 768v512h384l384 384v-1280l-384 384h-384zM1216 832q21 43 32 66.5t21.5 59.5t10.5 66t-10.5 66t-21.5 59.5t-32 66.5l96 96q96 -144 96 -288q0 -160 -96 -256zM1376 672q74 74 117 166t43 186t-43 186t-117 166l96 96q95 -71 143.5 -186.5t48.5 -261.5 t-48.5 -261.5t-143.5 -186.5z" />
6578 +<glyph unicode="&#xf200;" d="M0 1024q0 212 79.5 402t216 326.5t326.5 216t402 79.5t402 -79.5t326.5 -216t216 -326.5t79.5 -402t-79.5 -402t-216 -326.5t-326.5 -216t-402 -79.5t-402 79.5t-326.5 216t-216 326.5t-79.5 402zM128 1024q0 -307 173.5 -536.5t466.5 -327.5v224q0 224 128 224 q-125 0 -213.5 16t-146.5 47t-91.5 83t-47 115.5t-13.5 154.5q0 100 25 187t71 133q-28 71 -28 143t14 109l14 36q7 0 18 -1t44 -7.5t63 -18.5t67 -38.5t64 -62.5q144 24 300 24t276 -24q27 36 60 62.5t60.5 38.5t51.5 18.5t38 7.5l14 1q4 -5 10 -14.5t19 -40.5t20 -63 t4 -78.5t-21 -91.5q96 -144 96 -320q0 -113 -21 -187.5t-75 -128t-147.5 -77t-236.5 -23.5q49 -25 72.5 -77.5t23.5 -146.5v-224q293 98 466.5 327.5t173.5 536.5q0 176 -73 341.5t-194.5 287t-287 194.5t-341.5 73t-341.5 -73t-287 -194.5t-194.5 -287t-73 -341.5z" />
6579 +<glyph unicode="&#xf201;" d="M0 1024q0 206 82 395.5t219.5 327t327 219.5t395.5 82t395.5 -82t327 -219.5t219.5 -327t82 -395.5t-82 -395.5t-219.5 -327t-327 -219.5t-395.5 -82t-395.5 82t-327 219.5t-219.5 327t-82 395.5zM128 1024q0 -167 58 -319.5t166 -272.5q125 205 339 360t445 232 q-16 48 -80 176q-282 -86 -481.5 -111t-446.5 -1v-64zM160 1232q194 -22 444 14t388 82q-141 282 -320 528q-194 -85 -329.5 -247.5t-182.5 -376.5zM480 320q216 -192 544 -192q181 0 368 80q-33 300 -208 688q-222 -74 -410 -225.5t-294 -350.5zM832 1904 q102 -166 304 -512q6 2 86 31t118.5 45t108 47t122 64t93.5 69q-126 126 -290.5 199t-349.5 73q-32 0 -96 -8t-96 -8zM1200 1248q22 -29 36.5 -54.5t34 -67.5t25.5 -54q170 33 336 30t288 -30q-26 285 -160 464q-71 -57 -162 -104.5t-214.5 -100.5t-183.5 -83zM1344 928 q14 -27 43 -103t74.5 -231t74.5 -306q156 108 258 278t126 362q-276 46 -576 0z" />
6580 +<glyph unicode="&#xf202;" d="M0 381q50 -6 100 -6q293 0 522 180q-137 2 -244.5 83t-147.5 208q44 -7 79 -7q57 0 110 15q-145 29 -241 144.5t-96 267.5v5q86 -48 191 -53q-86 58 -136.5 150t-50.5 200q0 113 57 211q158 -194 383 -310t483 -129q-11 49 -11 96q0 174 123 297t297 123q89 0 168.5 -35 t138.5 -97q142 27 266 102q-47 -150 -184 -233q124 15 241 66q-84 -127 -210 -217q2 -36 2 -55q0 -168 -49 -337t-150 -323.5t-241 -273.5t-336 -190t-420 -71q-351 0 -644 189z" />
6581 +<glyph unicode="&#xf203;" d="M0 117q0 -48 34.5 -82.5t82.5 -34.5h1814q48 0 82.5 34.5t34.5 82.5v1814q0 48 -34.5 82.5t-82.5 34.5h-1814q-48 0 -82.5 -34.5t-34.5 -82.5v-1814zM900 969v303h222v258q0 78 26 147t77 124t136.5 87t194.5 32q55 0 108 -3t79 -6l26 -3l-7 -282h-193q-76 0 -101.5 -32 t-25.5 -101v-3v-2v-9v-207h329l-14 -303h-315v-841h-320v841h-222z" />
6582 +<glyph unicode="&#xf204;" d="M640 969v303h222v258q0 78 26 147t77 124t136.5 87t194.5 32q55 0 108 -3t79 -6l26 -3l-7 -282h-193q-76 0 -101.5 -32t-25.5 -101v-3v-2v-9v-207h329l-14 -303h-315v-841h-320v841h-222z" />
6583 +<glyph unicode="&#xf205;" d="M0 1024q0 208 81 397.5t218.5 327t327 218.5t397.5 81t398 -81t327 -218.5t218 -327t81 -397.5q0 -209 -81 -398.5t-218 -326.5t-326.5 -218t-398.5 -81q-208 0 -397.5 81t-327 218t-218.5 327t-81 398zM128 1024q0 -259 135.5 -473.5t359.5 -327.5l-421 1156 q-74 -168 -74 -355zM285 1530q4 0 13.5 -0.5t15.5 -0.5q70 0 127.5 2.5t80.5 4.5l22 3q29 2 46.5 -16t19.5 -40.5t-13 -43t-44 -24.5q-27 -4 -70 -8l295 -877l198 591l-104 283l-90 11q-38 2 -51.5 34t4.5 62t56 28q54 -10 201 -10q70 0 127.5 2.5t80.5 4.5l22 3 q38 2 56.5 -27t5 -60.5t-51.5 -36.5q-27 -4 -69 -8l293 -870l90 301q69 177 69 293q0 51 -14 107q-18 45 -40 81q-2 3 -15 24t-15.5 25t-13 22t-13 24.5t-10 22t-10 24.5t-6.5 22t-5 25t-1 24q0 63 42 110.5t106 49.5q-121 108 -274.5 168t-321.5 60q-226 0 -421 -105 t-318 -285zM772 165q123 -37 252 -37q152 0 296 51q0 1 -1 1l-1 2l-278 763zM1485 256q199 120 317 324t118 444q0 216 -99 409q4 -44 4 -68q0 -153 -69 -324z" />
6584 +<glyph unicode="&#xf206;" d="M128 486v485q125 -127 330 -127q30 0 59 3q-32 -61 -32 -118q0 -33 13 -63t28.5 -48.5t45.5 -47.5q-18 0 -54.5 -0.5t-55.5 -0.5q-183 0 -334 -83zM128 1599v97q0 93 65.5 158.5t158.5 65.5h1344q93 0 158.5 -65.5t65.5 -158.5v-224h-280v280h-140v-280h-280v-140h280 v-280h140v280h280v-980q0 -93 -65.5 -158.5t-158.5 -65.5h-539q5 28 5 50q0 143 -46.5 230t-189.5 194q-3 2 -20.5 15t-25 19t-25.5 20t-27.5 22.5t-24 22t-23 23.5t-17 22t-12.5 22.5t-4 20.5q0 52 23 87t99 94q180 141 180 324q0 113 -45 204.5t-128 139.5h160l135 142 h-607q-127 0 -241.5 -49t-194.5 -132zM134 301q56 89 166.5 143.5t241.5 53.5q84 -1 158 -26q19 -13 62 -42.5t61 -42t48 -37t44.5 -41.5t29 -41.5t21.5 -49.5q7 -29 7 -66q0 -16 -1 -24h-620q-79 0 -140 49t-78 124zM228 1307q-21 161 50.5 269.5t194.5 104.5 q121 -4 215.5 -118.5t116.5 -277.5q21 -160 -43 -256t-187 -92q-125 4 -225.5 108t-121.5 262z" />
6585 +<glyph unicode="&#xf207;" d="M384 1422q0 -58 40.5 -97.5t105.5 -39.5h1q67 0 108.5 39.5t41.5 97.5q-2 60 -42 98.5t-106 38.5q-67 0 -108 -39t-41 -98zM400 384h263v793h-263v-793zM809 384h264v443q0 45 8 64q16 40 50.5 68t85.5 28q133 0 133 -179v-424h264v455q0 175 -83.5 266t-220.5 91 q-50 0 -90.5 -12t-68.5 -34t-45 -41t-33 -44v112h-264v-793z" />
6586 +<glyph unicode="&#xf208;" d="M128 384v1280q0 106 75 181t181 75h1280q106 0 181 -75t75 -181v-1280q0 -106 -75 -181t-181 -75h-1280q-106 0 -181 75t-75 181zM384 1422q0 -58 40.5 -97.5t105.5 -39.5h1q67 0 108.5 39.5t41.5 97.5q-2 60 -42 98.5t-106 38.5q-67 0 -108 -39t-41 -98zM400 384h263 v793h-263v-793zM809 384h264v443q0 45 8 64q16 40 50.5 68t85.5 28q133 0 133 -179v-424h264v455q0 175 -83.5 266t-220.5 91q-50 0 -90.5 -12t-68.5 -34t-45 -41t-33 -44v112h-264v-793z" />
6587 +<glyph unicode="&#xf209;" d="M171 1260q0 109 35.5 219t110 213t179 182t254 126.5t323.5 47.5q176 0 327.5 -60.5t253.5 -161t160 -231t58 -270.5q0 -246 -85 -443t-241 -309.5t-355 -112.5q-99 0 -186.5 46.5t-121.5 110.5q-73 -290 -89 -347q-34 -123 -127 -270l-149 54q-7 167 22 290l162 688 q-40 81 -40 200q0 139 70.5 232.5t172.5 93.5q83 0 127 -53.5t44 -135.5q0 -51 -18.5 -124t-49 -170t-44.5 -154q-23 -99 37.5 -171t161.5 -72q117 0 209.5 92t142 244.5t49.5 334.5q0 214 -139 349t-387 135q-139 0 -257.5 -49.5t-197 -133t-122.5 -193t-44 -229.5 q0 -147 83 -247q18 -21 21.5 -34t-3.5 -37q-16 -61 -25 -101q-7 -24 -24.5 -32t-39.5 1q-127 51 -192.5 181.5t-65.5 300.5z" />
6588 +<glyph unicode="&#xf210;" d="M0 1024q0 208 81 398t218.5 327t327 218t397.5 81q209 0 398.5 -81t326.5 -218t218 -326.5t81 -398.5t-81 -398.5t-218 -326.5t-326.5 -218t-398.5 -81q-147 0 -290 42q74 116 103 219l72 282q28 -53 99 -90.5t151 -37.5q162 0 288.5 91.5t195.5 251t69 359.5 q0 114 -47 220t-130 187.5t-206.5 130.5t-265.5 49q-141 0 -262 -38.5t-205.5 -103t-145.5 -147.5t-89.5 -172.5t-28.5 -178.5q0 -138 53 -243.5t156 -147.5q18 -8 32.5 -1t18.5 26q2 9 10 41t11 41q5 19 2.5 30t-16.5 28q-68 78 -68 200q0 97 35.5 186t99.5 156.5t160 108 t209 40.5q201 0 313.5 -109.5t112.5 -283.5q0 -148 -40 -271.5t-115 -198t-169 -74.5q-82 0 -131.5 58.5t-30.5 138.5q11 46 35.5 125t39.5 138t15 101q0 66 -35.5 109.5t-102.5 43.5q-82 0 -139.5 -76t-57.5 -189q0 -43 8 -83.5t16 -59.5l9 -19q-113 -475 -132 -558 q-24 -97 -18 -235q-275 120 -444 374t-169 564z" />
6589 +<glyph unicode="&#xf211;" d="M160 1024q0 -172 122 -294t294 -122t294 122t122 294t-122 294t-294 122t-294 -122t-122 -294zM1056 1024q0 -172 122 -294t294 -122t294 122t122 294t-122 294t-294 122t-294 -122t-122 -294z" />
6590 +<glyph unicode="&#xf300;" d="M256 896v384q0 106 75 181t181 75h1024q106 0 181 -75t75 -181v-384q0 -106 -75 -181t-181 -75h-448l-448 -448v448h-128q-106 0 -181 75t-75 181z" />
6591 +<glyph unicode="&#xf301;" d="M384 512v1024h384l64 -128h448v-128h-640l-128 -256h128l64 128h960l-256 -640h-1024z" />
6592 +<glyph unicode="&#xf302;" d="M256 768l768 768h512v-512l-768 -768zM1152 1280q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5t-37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5z" />
6593 +<glyph unicode="&#xf303;" d="M256 1088q0 143 55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5t-55.5 -273.5t-150 -225t-225 -150t-273.5 -55.5t-273.5 55.5t-225 150t-150 225t-55.5 273.5zM384 1088q0 -117 45.5 -223.5t123 -184t184 -123t223.5 -45.5 t223.5 45.5t184 123t123 184t45.5 223.5t-45.5 223.5t-123 184t-184 123t-223.5 45.5t-223.5 -45.5t-184 -123t-123 -184t-45.5 -223.5zM896 1062v474h128v-421l298 -298l-90 -91z" />
6594 +<glyph unicode="&#xf304;" d="M512 384v256q0 159 112.5 271.5t271.5 112.5h256q159 0 271.5 -112.5t112.5 -271.5v-256h-1024zM768 1408q0 106 75 181t181 75t181 -75t75 -181t-75 -181t-181 -75t-181 75t-75 181z" />
6595 +<glyph unicode="&#xf305;" d="M256 384v1280h256v128h128v-128h640v128h128v-128h256v-1280h-1408zM384 640q0 -53 37.5 -90.5t90.5 -37.5h896q53 0 90.5 37.5t37.5 90.5v640q0 53 -37.5 90.5t-90.5 37.5h-896q-53 0 -90.5 -37.5t-37.5 -90.5v-640zM768 1216q0 26 19 45t45 19h128q26 0 45 -19t19 -45 v-512q0 -26 -19 -45t-45 -19t-45 19t-19 45v448h-64q-26 0 -45 19t-19 45z" />
6596 +<glyph unicode="&#xf306;" d="M256 384v1280h256v128h128v-128h640v128h128v-128h256v-1280h-1408zM384 640q0 -53 37.5 -90.5t90.5 -37.5h896q53 0 90.5 37.5t37.5 90.5v640q0 53 -37.5 90.5t-90.5 37.5h-896q-53 0 -90.5 -37.5t-37.5 -90.5v-640zM768 1216q0 26 19 45t45 19h256h2h1h3 q22 -2 38.5 -18t19.5 -39v-2v-2v-1v-2q0 -5 -2 -15l-128 -512q-6 -26 -28.5 -40t-48.5 -7q-26 6 -40 28.5t-7 48.5l108 433h-174q-26 0 -45 19t-19 45z" />
6597 +<glyph unicode="&#xf307;" d="M256 384v1280h256v128h128v-128h640v128h128v-128h256v-1280h-1408zM384 640q0 -53 37.5 -90.5t90.5 -37.5h896q53 0 90.5 37.5t37.5 90.5v640q0 53 -37.5 90.5t-90.5 37.5h-896q-53 0 -90.5 -37.5t-37.5 -90.5v-640zM512 640v128h128v-128h-128zM512 896v128h128v-128 h-128zM768 640v128h128v-128h-128zM768 896v128h128v-128h-128zM768 1152v128h128v-128h-128zM1024 640v128h128v-128h-128zM1024 896v128h128v-128h-128zM1024 1152v128h128v-128h-128zM1280 896v128h128v-128h-128zM1280 1152v128h128v-128h-128z" />
6598 +<glyph unicode="&#xf400;" d="M256 1216q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5q0 -184 -111 -337l495 -495l-128 -128l-495 495q-153 -111 -337 -111q-117 0 -223.5 45.5t-184 123t-123 184t-45.5 223.5zM384 1216q0 -185 131.5 -316.5 t316.5 -131.5q186 0 317 131.5t131 316.5t-131 316.5t-317 131.5q-185 0 -316.5 -131.5t-131.5 -316.5z" />
6599 +<glyph unicode="&#xf401;" d="M256 1216q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5q0 -184 -111 -337l495 -495l-128 -128l-495 495q-153 -111 -337 -111q-117 0 -223.5 45.5t-184 123t-123 184t-45.5 223.5zM384 1216q0 -185 131.5 -316.5 t316.5 -131.5q186 0 317 131.5t131 316.5t-131 316.5t-317 131.5q-185 0 -316.5 -131.5t-131.5 -316.5zM512 1152v128h640v-128h-640z" />
6600 +<glyph unicode="&#xf402;" d="M256 1216q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5q0 -184 -111 -337l495 -495l-128 -128l-495 495q-153 -111 -337 -111q-117 0 -223.5 45.5t-184 123t-123 184t-45.5 223.5zM384 1216q0 -185 131.5 -316.5 t316.5 -131.5q186 0 317 131.5t131 316.5t-131 316.5t-317 131.5q-185 0 -316.5 -131.5t-131.5 -316.5zM512 1152v128h256v256h128v-256h256v-128h-256v-256h-128v256h-256z" />
6601 +<glyph unicode="&#xf403;" d="M0 1024l506 506q101 103 234.5 160.5t283.5 57.5t283.5 -57.5t233.5 -159.5l507 -507l-506 -507q-101 -103 -234.5 -160t-283.5 -57t-283.5 57.5t-233.5 160.5zM272 1024l370 -371q77 -78 175.5 -119.5t206.5 -41.5t206 41.5t174 118.5l373 372l-371 371 q-158 161 -382 161q-108 0 -206.5 -41t-173.5 -119zM640 1024q0 159 112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5t-112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5zM1024 1152q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5t-37.5 90.5t-90.5 37.5 t-90.5 -37.5t-37.5 -90.5z" />
6602 +<glyph unicode="&#xf404;" d="M0 1024l506 506q101 103 234.5 160.5t283.5 57.5q193 0 358 -95l-143 -143q-103 46 -215 46q-108 0 -206.5 -41t-173.5 -119l-372 -372l240 -240l-136 -136zM339 429l90 -90l1280 1280l-90 90zM640 1024q0 159 112.5 271.5t271.5 112.5q44 0 98 -14l-468 -468 q-14 54 -14 98zM666 395l143 143q103 -46 215 -46q108 0 206 41.5t174 118.5l373 372l-241 241l136 135l376 -376l-506 -507q-101 -103 -234.5 -160t-283.5 -57q-193 0 -358 95zM926 654l468 468q14 -54 14 -98q0 -159 -112.5 -271.5t-271.5 -112.5q-44 0 -98 14z" />
6603 +<glyph unicode="&#xf405;" d="M640 768l320 320l-320 320l128 128l320 -320l320 320l128 -128l-320 -320l320 -320l-128 -128l-320 320l-320 -320z" />
6604 +<glyph unicode="&#xf406;" d="M128 256l832 832l-832 832l128 128l832 -832l832 832l128 -128l-832 -832l832 -832l-128 -128l-832 832l-832 -832z" />
6605 +<glyph unicode="&#xf407;" d="M384 1280q0 106 75 181t181 75h140q20 56 69.5 92t110.5 36q62 0 111 -35.5t69 -92.5h140q106 0 181 -75t75 -181h-128v-768q0 -53 -37.5 -90.5t-90.5 -37.5h-640q-53 0 -90.5 37.5t-37.5 90.5v768h-128zM640 576q0 -26 19 -45t45 -19t45 19t19 45v640q0 26 -19 45 t-45 19t-45 -19t-19 -45v-640zM896 576q0 -26 19 -45t45 -19t45 19t19 45v640q0 26 -19 45t-45 19t-45 -19t-19 -45v-640zM1152 576q0 -26 19 -45t45 -19t45 19t19 45v640q0 26 -19 45t-45 19t-45 -19t-19 -45v-640z" />
6606 +<glyph unicode="&#xf408;" d="M256 1151l476 -330l-183 -535l475 332l475 -332l-183 535l476 329h-587l-181 535l-180 -534h-588z" />
6607 +<glyph unicode="&#xf409;" d="M384 1024l640 640l640 -640l-128 -128l-512 512l-512 -512zM640 512v384l384 384l384 -384v-384h-256v384h-256v-384h-256z" />
6608 +<glyph unicode="&#xf410;" d="M0 384l640 640l384 -384l384 384l640 -640h-2048zM0 512v1152l576 -576zM0 1792h2048l-1024 -1024zM1472 1088l576 576v-1152z" />
6609 +<glyph unicode="&#xf411;" d="M384 384v448l896 896l448 -448l-896 -896h-448zM512 768l256 -256l128 128l-256 256zM685 941l96 -96l595 595l-96 96zM845 781l96 -96l595 595l-96 96z" />
6610 +<glyph unicode="&#xf412;" d="M256 640v704l384 384v-704h640v448l640 -640l-640 -640v448h-1024z" />
6611 +<glyph unicode="&#xf413;" d="M128 384q0 106 75 181t181 75t181 -75t75 -181t-75 -181t-181 -75t-181 75t-75 181zM128 971v345q240 0 459 -94t377.5 -253.5t252.5 -379.5t94 -461h-345q0 170 -63.5 324t-181.5 273q-119 119 -272 182.5t-321 63.5zM129 1582v345q243 0 475 -64.5t428.5 -181 t362 -282.5t281 -363.5t180 -430.5t64.5 -477h-345q0 197 -52 385.5t-145.5 348t-227 294t-292 228t-346 146t-383.5 52.5z" />
6612 +<glyph unicode="&#xf414;" d="M21 230q-57 102 31 244l760 1237q57 93 134.5 126.5t155 0t135.5 -126.5l759 -1237q88 -142 31 -244t-224 -102h-1557q-168 0 -225 102zM896 512q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5t-37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5zM896 896 q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5v384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5v-384z" />
6613 +<glyph unicode="&#xf415;" d="M128 1024h400q45 0 79.5 27.5t44.5 69.5q33 125 136.5 206t235.5 81q154 0 270 -114q38 -38 90.5 -38t90.5 38q37 38 37 91t-37 90q-88 89 -204.5 139t-246.5 50q-194 0 -353 -106t-234 -278h-309v-256zM536 663q0 -53 37 -90q89 -89 205 -139t246 -50q194 0 353 106 t234 278h309v256h-400q-45 0 -79.5 -27.5t-44.5 -69.5q-33 -125 -136.5 -206t-235.5 -81q-156 0 -269 115q-38 37 -91 37t-91 -38q-37 -38 -37 -91zM768 1024q0 -106 75 -181t181 -75t181 75t75 181t-75 181t-181 75t-181 -75t-75 -181z" />
6614 +<glyph unicode="&#xf416;" d="M512 832v320h128v-320q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5t93.5 226.5v640q0 80 -56 136t-136 56t-136 -56t-56 -136v-512q0 -26 19 -45t45 -19t45 19t19 45v452h128v-452q0 -80 -56 -136t-136 -56t-136 56t-56 136v512q0 133 93.5 226.5t226.5 93.5t226.5 -93.5 t93.5 -226.5v-640q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5z" />
6615 +<glyph unicode="&#xf417;" d="M384 1216q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5t-44.5 -222.5t-124.5 -185.5l-407 -406l-407 406q-80 80 -124.5 185.5t-44.5 222.5zM640 1216q0 -133 93.5 -226.5t226.5 -93.5t226.5 93.5t93.5 226.5t-93.5 226.5 t-226.5 93.5t-226.5 -93.5t-93.5 -226.5z" />
6616 +<glyph unicode="&#xf418;" d="M608 1056l128 128l224 -192l448 512l128 -96l-512 -768h-128z" />
6617 +<glyph unicode="&#xf419;" d="M0 256v256h2048v-256h-2048zM0 896v256h2048v-256h-2048zM0 1536v256h2048v-256h-2048z" />
6618 +<glyph unicode="&#xf420;" d="M384 512l640 640l640 -640h-1280zM384 1280v128h1280v-128h-1280z" />
6619 +<glyph unicode="&#xf421;" d="M384 896v256h1152v-256h-1152z" />
6620 +<glyph unicode="&#xf422;" d="M384 512v1024h1152v-1024h-1152zM512 640h896v640h-896v-640z" />
6621 +<glyph unicode="&#xf500;" d="M128 0l960 960l960 -960h-1920z" />
6622 +<glyph unicode="&#xf501;" d="M0 128l960 960l-960 960v-1920z" />
6623 +<glyph unicode="&#xf502;" d="M128 2048l960 -960l960 960h-1920z" />
6624 +<glyph unicode="&#xf503;" d="M1088 1088l960 960v-1920z" />
6625 +</font>
6626 +</defs></svg>
6627 \ No newline at end of file
6628
6629 diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.ttf b/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.ttf
6630 new file mode 100644
6631 index 0000000..45228d9
6632 Binary files /dev/null and b/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.ttf differ
6633
6634 diff --git a/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.woff b/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.woff
6635 new file mode 100644
6636 index 0000000..a64be4b
6637 Binary files /dev/null and b/plugins/jetpack/modules/minileven/theme/pub/minileven/inc/fonts/genericons-regular-webfont.woff differ
6638
6639 diff --git a/plugins/jetpack/modules/omnisearch.php b/plugins/jetpack/modules/omnisearch.php
6640 new file mode 100644
6641 index 0000000..a5db2a5
6642 --- /dev/null
6643 +++ b/plugins/jetpack/modules/omnisearch.php
6644 @@ -0,0 +1,14 @@
6645 +<?php
6646 +
6647 +/**
6648 + * Module Name: Omnisearch
6649 + * Module Description: A single search box, that lets you search many different things.
6650 + * Sort Order: 8
6651 + * First Introduced: 2.3
6652 + * Requires Connection: No
6653 + */
6654 +
6655 +// Only do Jetpack Omnisearch if there isn't already a Core WP_Omnisearch Class.
6656 +if ( ! class_exists( 'WP_Omnisearch' ) )
6657 + require_once( dirname( __FILE__ ) . '/omnisearch/omnisearch-core.php' );
6658 +
6659
6660 diff --git a/plugins/jetpack/modules/omnisearch/omnisearch-comments.php b/plugins/jetpack/modules/omnisearch/omnisearch-comments.php
6661 new file mode 100644
6662 index 0000000..7f770ef
6663 --- /dev/null
6664 +++ b/plugins/jetpack/modules/omnisearch/omnisearch-comments.php
6665 @@ -0,0 +1,48 @@
6666 +<?php
6667 +
6668 +if( ! class_exists( 'WP_Comments_List_Table' ) )
6669 + require_once( ABSPATH . 'wp-admin/includes/class-wp-comments-list-table.php' );
6670 +
6671 +class Jetpack_Omnisearch_Comments extends WP_Comments_List_Table {
6672 + static $instance;
6673 + var $checkbox = false;
6674 +
6675 + function __construct() {
6676 + self::$instance = $this;
6677 + add_filter( 'omnisearch_results', array( $this, 'search'), 10, 2 );
6678 + }
6679 +
6680 + function search( $results, $search_term ) {
6681 + $search_url = esc_url( admin_url( sprintf( 'edit-comments.php?s=%s', urlencode( $search_term ) ) ) );
6682 + $search_link = sprintf( ' <a href="%s" class="add-new-h2">%s</a>', $search_url, esc_html__('Search Comments', 'jetpack') );
6683 + $html = '<h2>' . esc_html__('Comments', 'jetpack') . $search_link . '</h2>';
6684 + parent::__construct();
6685 +
6686 + ob_start();
6687 + $this->prepare_items();
6688 + $this->_column_headers = array( $this->get_columns(), array(), array() );
6689 + $this->display();
6690 + $html .= ob_get_clean();
6691 +
6692 + $label = __( 'Comments', 'jetpack' );
6693 + $results[ $label ] = $html;
6694 + return $results;
6695 + }
6696 +
6697 + function get_per_page( $comment_status = 'all' ) {
6698 + return apply_filters( 'omnisearch_num_results', 5 );
6699 + }
6700 +
6701 + function get_sortable_columns() {
6702 + return array();
6703 + }
6704 +
6705 + function get_bulk_actions() {
6706 + return array();
6707 + }
6708 +
6709 + function pagination( $which ) {}
6710 +
6711 + function extra_tablenav( $which ) {}
6712 +}
6713 +
6714
6715 diff --git a/plugins/jetpack/modules/omnisearch/omnisearch-core.php b/plugins/jetpack/modules/omnisearch/omnisearch-core.php
6716 new file mode 100644
6717 index 0000000..1b19a46
6718 --- /dev/null
6719 +++ b/plugins/jetpack/modules/omnisearch/omnisearch-core.php
6720 @@ -0,0 +1,181 @@
6721 +<?php
6722 +
6723 +// Include this here so that other plugins can extend it if they like.
6724 +require_once( dirname(__FILE__) . '/omnisearch-posts.php' );
6725 +
6726 +class Jetpack_Omnisearch {
6727 + static $instance;
6728 + static $num_results = 5;
6729 +
6730 + function __construct() {
6731 + self::$instance = $this;
6732 + add_action( 'wp_loaded', array( $this, 'wp_loaded' ) );
6733 + add_action( 'admin_init', array( $this, 'add_providers' ) );
6734 + add_action( 'jetpack_admin_menu', array( $this, 'jetpack_admin_menu' ) );
6735 + add_action( 'admin_menu', array( $this, 'admin_menu' ), 20 );
6736 + if( ! jetpack_is_mobile() ) {
6737 + add_action( 'admin_bar_menu', array( $this, 'admin_bar_search' ), 4 );
6738 + }
6739 + add_filter( 'omnisearch_num_results', array( $this, 'omnisearch_num_results' ) );
6740 + }
6741 +
6742 + static function add_providers() {
6743 + // omnisearch-posts.php is included above, so that other plugins can more easily extend it.
6744 + new Jetpack_Omnisearch_Posts;
6745 + new Jetpack_Omnisearch_Posts( 'page' );
6746 +
6747 + require_once( dirname(__FILE__) . '/omnisearch-comments.php' );
6748 + new Jetpack_Omnisearch_Comments;
6749 +
6750 + if ( current_user_can( 'install_plugins' ) ) {
6751 + require_once( dirname(__FILE__) . '/omnisearch-plugins.php' );
6752 + new Jetpack_Omnisearch_Plugins;
6753 + }
6754 +
6755 + do_action( 'omnisearch_add_providers' );
6756 + }
6757 +
6758 + static function omnisearch_num_results( $num ) {
6759 + return self::$num_results;
6760 + }
6761 +
6762 + function wp_loaded() {
6763 + $deps = null;
6764 + if ( wp_style_is( 'genericons', 'registered' ) ) {
6765 + $deps = array( 'genericons' );
6766 + }
6767 +
6768 + wp_register_style( 'omnisearch-admin', plugins_url( 'omnisearch.css', __FILE__ ), $deps );
6769 + wp_register_style( 'omnisearch-jetpack', plugins_url( 'omnisearch-jetpack.css', __FILE__ ) );
6770 + }
6771 +
6772 + function jetpack_admin_menu() {
6773 + remove_submenu_page( 'index.php', 'omnisearch' );
6774 + $this->slug = add_submenu_page( 'jetpack', __('Omnisearch', 'jetpack'), __('Omnisearch', 'jetpack'), 'edit_posts', 'omnisearch', array( $this, 'omnisearch_page' ) );
6775 + add_action( "admin_print_styles-{$this->slug}", array( $this, 'admin_print_styles_jetpack' ) );
6776 + }
6777 +
6778 + function admin_menu() {
6779 + $this->slug = add_dashboard_page( __('Omnisearch', 'jetpack'), __('Omnisearch', 'jetpack'), 'edit_posts', 'omnisearch', array( $this, 'omnisearch_page' ) );
6780 + add_action( "admin_print_styles-{$this->slug}", array( $this, 'admin_print_styles' ) );
6781 + }
6782 +
6783 + function admin_print_styles() {
6784 + wp_enqueue_style( 'omnisearch-admin' );
6785 + }
6786 +
6787 + function admin_print_styles_jetpack() {
6788 + wp_enqueue_style( 'omnisearch-admin' );
6789 + wp_enqueue_style( 'omnisearch-jetpack' );
6790 + }
6791 +
6792 + function omnisearch_page() {
6793 + $results = array();
6794 + $s = isset( $_GET['s'] ) ? $_GET['s'] : '';
6795 + if( $s ) {
6796 + $results = apply_filters( 'omnisearch_results', $results, $s );
6797 + }
6798 + ?>
6799 + <div class="wrap">
6800 + <h2 class="page-title"><?php esc_html_e('Omnisearch', 'jetpack'); ?> <small><?php esc_html_e('search everything', 'jetpack'); ?></small></h2>
6801 + <br class="clear" />
6802 + <?php echo self::get_omnisearch_form( array(
6803 + 'form_class' => 'omnisearch-form',
6804 + 'search_class' => 'omnisearch',
6805 + 'search_placeholder' => '',
6806 + 'submit_class' => 'omnisearch-submit',
6807 + 'alternate_submit' => true,
6808 + ) ); ?>
6809 + <?php if( ! empty( $results ) ): ?>
6810 + <h3 id="results-title"><?php esc_html_e('Results:', 'jetpack'); ?></h3>
6811 + <div class="jump-to"><strong><?php esc_html_e('Jump to:', 'jetpack'); ?></strong>
6812 + <?php foreach( $results as $label => $result ) : ?>
6813 + <a href="#result-<?php echo sanitize_title( $label ); ?>"><?php echo esc_html( $label ); ?></a>
6814 + <?php endforeach; ?>
6815 + </div>
6816 + <br class="clear" />
6817 + <script>var search_term = '<?php echo esc_js( $s ); ?>', num_results = <?php echo intval( apply_filters( 'omnisearch_num_results', 5 ) ); ?>;</script>
6818 + <ul class="omnisearch-results">
6819 + <?php foreach( $results as $label => $result ) : ?>
6820 + <li id="result-<?php echo sanitize_title( $label ); ?>" data-label="<?php echo esc_attr( $label ); ?>">
6821 + <?php echo $result; ?>
6822 + <a class="back-to-top" href="#results-title"><?php esc_html_e('Back to Top &uarr;', 'jetpack'); ?></a>
6823 + </li>
6824 + <?php endforeach; ?>
6825 + </ul>
6826 + <?php endif; ?>
6827 + </div><!-- /wrap -->
6828 + <?php
6829 + }
6830 +
6831 + function admin_bar_search( $wp_admin_bar ) {
6832 + if( ! is_admin() || ! current_user_can( 'edit_posts' ) )
6833 + return;
6834 +
6835 + $form = self::get_omnisearch_form( array(
6836 + 'form_id' => 'adminbarsearch',
6837 + 'search_id' => 'adminbar-search',
6838 + 'search_class' => 'adminbar-input',
6839 + 'submit_class' => 'adminbar-button',
6840 + ) );
6841 +
6842 + $form .= "<style>
6843 + #adminbar-search::-webkit-input-placeholder,
6844 + #adminbar-search:-moz-placeholder,
6845 + #adminbar-search::-moz-placeholder,
6846 + #adminbar-search:-ms-input-placeholder {
6847 + text-shadow: none;
6848 + }
6849 + </style>";
6850 +
6851 + $wp_admin_bar->add_menu( array(
6852 + 'parent' => 'top-secondary',
6853 + 'id' => 'search',
6854 + 'title' => $form,
6855 + 'meta' => array(
6856 + 'class' => 'admin-bar-search',
6857 + 'tabindex' => -1,
6858 + )
6859 + ) );
6860 + }
6861 +
6862 + static function get_omnisearch_form( $args = array() ) {
6863 + $defaults = array(
6864 + 'form_id' => null,
6865 + 'form_class' => null,
6866 + 'search_class' => null,
6867 + 'search_id' => null,
6868 + 'search_value' => isset( $_REQUEST['s'] ) ? $_REQUEST['s'] : null,
6869 + 'search_placeholder' => __( 'Search Everything', 'jetpack' ),
6870 + 'submit_class' => 'button',
6871 + 'submit_value' => __( 'Search', 'jetpack' ),
6872 + 'alternate_submit' => false,
6873 + );
6874 + extract( array_map( 'esc_attr', wp_parse_args( $args, $defaults ) ) );
6875 +
6876 + $rand = rand();
6877 + if( empty( $form_id ) )
6878 + $form_id = "omnisearch_form_$rand";
6879 + if( empty( $search_id ) )
6880 + $search_id = "omnisearch_search_$rand";
6881 +
6882 + ob_start();
6883 + ?>
6884 +
6885 + <form action="<?php echo esc_url( admin_url( 'admin.php' ) ); ?>" method="get" class="<?php echo $form_class; ?>" id="<?php echo $form_id; ?>">
6886 + <input type="hidden" name="page" value="omnisearch" />
6887 + <input name="s" type="search" class="<?php echo $search_class; ?>" id="<?php echo $search_id; ?>" value="<?php echo $search_value; ?>" placeholder="<?php echo $search_placeholder; ?>" />
6888 + <?php if ( $alternate_submit ) : ?>
6889 + <button type="submit" class="<?php echo $submit_class; ?>"><span><?php echo $submit_value; ?></span></button>
6890 + <?php else : ?>
6891 + <input type="submit" class="<?php echo $submit_class; ?>" value="<?php echo $submit_value; ?>" />
6892 + <?php endif; ?>
6893 + </form>
6894 +
6895 + <?php
6896 + return apply_filters( 'get_omnisearch_form', ob_get_clean(), $args, $defaults );
6897 + }
6898 +
6899 +}
6900 +new Jetpack_Omnisearch;
6901 +
6902
6903 diff --git a/plugins/jetpack/modules/omnisearch/omnisearch-jetpack.css b/plugins/jetpack/modules/omnisearch/omnisearch-jetpack.css
6904 new file mode 100644
6905 index 0000000..d100c40
6906 --- /dev/null
6907 +++ b/plugins/jetpack/modules/omnisearch/omnisearch-jetpack.css
6908 @@ -0,0 +1,35 @@
6909 +
6910 +.wp-admin #wpwrap {
6911 + background: url('../../_inc/images/header-clouds.png') 200% 0 repeat-x;
6912 +}
6913 +
6914 +@media print,
6915 + (-o-min-device-pixel-ratio: 5/4),
6916 + (-webkit-min-device-pixel-ratio: 1.25),
6917 + (min-resolution: 120dpi) {
6918 + #wpwrap {
6919 + background: url('../../_inc/images/header-clouds-2x.png') 0 0 repeat-x;
6920 + background-size: 1600px 400px;
6921 + }
6922 +}
6923 +
6924 +ul#adminmenu a.wp-has-current-submenu:after,
6925 +ul#adminmenu > li.current > a.current:after {
6926 + border-right-color:#8da94c;
6927 + display: none;
6928 +}
6929 +
6930 +h2.page-title {
6931 + color: #fff;
6932 + text-shadow: 0 1px 1px rgba(0,0,0,0.5);
6933 +}
6934 +
6935 +#results-title,
6936 +.jump-to {
6937 + color: #fff;
6938 + text-shadow: 0 1px 1px rgba(0,0,0,0.5);
6939 +}
6940 +
6941 +.omnisearch-results > li:first-child > h2 {
6942 + text-shadow: none;
6943 +}
6944
6945 diff --git a/plugins/jetpack/modules/omnisearch/omnisearch-plugins.php b/plugins/jetpack/modules/omnisearch/omnisearch-plugins.php
6946 new file mode 100644
6947 index 0000000..76df608
6948 --- /dev/null
6949 +++ b/plugins/jetpack/modules/omnisearch/omnisearch-plugins.php
6950 @@ -0,0 +1,61 @@
6951 +<?php
6952 +
6953 +if( ! class_exists( 'WP_Plugin_Install_List_Table' ) )
6954 + require_once( ABSPATH . 'wp-admin/includes/class-wp-plugin-install-list-table.php' );
6955 +
6956 +class Jetpack_Omnisearch_Plugins extends WP_Plugin_Install_List_Table {
6957 + static $instance;
6958 +
6959 + function __construct() {
6960 + self::$instance = $this;
6961 + add_filter( 'omnisearch_results', array( $this, 'search'), 10, 2 );
6962 + add_action( 'wp_ajax_omnisearch_plugins', array( $this, 'wp_ajax_omnisearch_plugins' ) );
6963 + }
6964 +
6965 + function search( $results, $search_term ) {
6966 + wp_enqueue_script( 'plugin-install' );
6967 + add_thickbox();
6968 +
6969 + $search_url = esc_url( admin_url( sprintf( 'plugin-install.php?tab=search&s=%s', urlencode( $search_term ) ) ) );
6970 + $search_link = sprintf( ' <a href="%s" class="add-new-h2">%s</a>', $search_url, esc_html__('Search Plugins', 'jetpack') );
6971 + $html = '<h2>' . esc_html__('Plugins', 'jetpack') . $search_link . '</h2>';
6972 +
6973 + $html .= '<div id="' . __CLASS__ . '_results">' . esc_html__('Loading &hellip;', 'jetpack') . '</div>';
6974 + $html .= '<script>jQuery("#' . __CLASS__ . '_results").load(ajaxurl,{action:"omnisearch_plugins",search_term:search_term,num_results:num_results});</script>';
6975 +
6976 + $label = __( 'Plugins', 'jetpack' );
6977 + $results[ $label ] = $html;
6978 + return $results;
6979 + }
6980 +
6981 + function results_html( $search_term, $num_results = null ) {
6982 + $_GET['tab'] = 'search';
6983 + $GLOBALS['hook_suffix'] = 'foo';
6984 + $_REQUEST['s'] = $search_term;
6985 + parent::__construct();
6986 +
6987 + ob_start();
6988 + $this->prepare_items();
6989 + $num_results = intval( $num_results ) ? intval( $num_results ) : apply_filters( 'omnisearch_num_results', 5 );
6990 + $this->items = array_slice( $this->items, 0, $num_results );
6991 + remove_action( 'install_plugins_table_header', 'install_search_form' );
6992 + $this->display();
6993 + $html = ob_get_clean();
6994 +
6995 + return $html;
6996 + }
6997 +
6998 + function wp_ajax_omnisearch_plugins() {
6999 + $search_term = $_REQUEST['search_term'];
7000 + $num_results = isset( $_REQUEST['num_results'] ) ? $_REQUEST['num_results'] : null;
7001 + echo $this->results_html( $search_term, $num_results );
7002 + exit;
7003 + }
7004 +
7005 + function get_bulk_actions() {
7006 + return array();
7007 + }
7008 +
7009 + function pagination( $which ) {}
7010 +}
7011 +
7012
7013 diff --git a/plugins/jetpack/modules/omnisearch/omnisearch-posts.php b/plugins/jetpack/modules/omnisearch/omnisearch-posts.php
7014 new file mode 100644
7015 index 0000000..61b3347
7016 --- /dev/null
7017 +++ b/plugins/jetpack/modules/omnisearch/omnisearch-posts.php
7018 @@ -0,0 +1,122 @@
7019 +<?php
7020 +
7021 +if( ! class_exists( 'WP_List_Table' ) )
7022 + require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
7023 +
7024 +class Jetpack_Omnisearch_Posts extends WP_List_Table {
7025 + var $post_type = 'post',
7026 + $post_type_object;
7027 +
7028 + function __construct( $post_type = 'post' ) {
7029 + $this->post_type = $post_type;
7030 + add_filter( 'omnisearch_results', array( $this, 'search'), 10, 2 );
7031 + }
7032 +
7033 + function search( $results, $search_term ) {
7034 + if( ! post_type_exists( $this->post_type ) )
7035 + return $results;
7036 +
7037 + parent::__construct();
7038 +
7039 + $this->post_type_obj = get_post_type_object( $this->post_type );
7040 +
7041 + $search_url = esc_url( admin_url( sprintf( 'edit.php?post_type=%s&s=%s', urlencode( $this->post_type_obj->name ), urlencode( $search_term ) ) ) );
7042 + $search_link = sprintf( ' <a href="%s" class="add-new-h2">%s</a>', $search_url, esc_html( $this->post_type_obj->labels->search_items ) );
7043 + $html = '<h2>' . esc_html( $this->post_type_obj->labels->name ) . $search_link .'</h2>';
7044 +
7045 + $num_results = apply_filters( 'omnisearch_num_results', 5 );
7046 +
7047 + $this->posts = get_posts( array( 's' => $search_term, 'post_type' => $this->post_type, 'posts_per_page' => $num_results, 'post_status' => 'any' ) );
7048 +
7049 + $this->prepare_items();
7050 +
7051 + ob_start();
7052 + $this->display();
7053 + $html .= ob_get_clean();
7054 +
7055 + $results[ $this->post_type_obj->labels->name ] = $html;
7056 + return $results;
7057 + }
7058 +
7059 + function get_columns() {
7060 + $columns = array(
7061 + # 'id' => __('ID', 'jetpack'),
7062 + 'post_title' => __('Title', 'jetpack'),
7063 + 'snippet' => __('Snippet', 'jetpack'),
7064 + 'date' => __('Date', 'jetpack'),
7065 + );
7066 + return $columns;
7067 + }
7068 +
7069 + function prepare_items() {
7070 + $columns = $this->get_columns();
7071 + $hidden = array();
7072 + $sortable = array();
7073 + $this->_column_headers = array( $columns, $hidden, $sortable );
7074 + $this->items = $this->posts;
7075 + }
7076 +
7077 + function column_post_title( $post ) {
7078 + $actions = array();
7079 + if ( current_user_can( $this->post_type_obj->cap->edit_post, $post ) ) {
7080 + $actions['edit'] = sprintf( '<a href="%s">%s</a>', esc_url( get_edit_post_link( $post->ID ) ), esc_html( $this->post_type_obj->labels->edit_item ) );
7081 + }
7082 + if ( current_user_can( $this->post_type_obj->cap->delete_post, $post ) ) {
7083 + $actions['delete'] = sprintf( '<a href="%s">%s</a>', esc_url( get_delete_post_link( $post->ID ) ), esc_html__('Trash', 'jetpack') );
7084 + }
7085 + $actions['view'] = sprintf( '<a href="%s">%s</a>', esc_url( get_permalink( $post->ID ) ), esc_html( $this->post_type_obj->labels->view_item ) );
7086 + return wptexturize( $post->post_title ) . $this->row_actions( $actions );
7087 + }
7088 +
7089 + function column_date( $post ) {
7090 + $html = '';
7091 +
7092 + if ( '0000-00-00 00:00:00' == $post->post_date ) {
7093 + $t_time = $h_time = __('Unpublished', 'jetpack');
7094 + $time_diff = 0;
7095 + } else {
7096 + $t_time = date( __('Y/m/d g:i:s A', 'jetpack'), mysql2date( 'G', $post->post_date ) );
7097 + $m_time = $post->post_date;
7098 + $time = get_post_time( 'G', true, $post );
7099 +
7100 + $time_diff = time() - $time;
7101 +
7102 + if ( $time_diff > 0 && $time_diff < DAY_IN_SECONDS )
7103 + $h_time = sprintf( __('%s ago', 'jetpack'), human_time_diff( $time ) );
7104 + else
7105 + $h_time = mysql2date( __('Y/m/d', 'jetpack'), $m_time );
7106 + }
7107 +
7108 + $html .= '<abbr title="' . esc_attr( $t_time ) . '">' . esc_html( $h_time ) . '</abbr>';
7109 + $html .= '<br />';
7110 + if ( 'publish' == $post->post_status ) {
7111 + $html .= esc_html__('Published', 'jetpack');
7112 + } elseif ( 'future' == $post->post_status ) {
7113 + if ( $time_diff > 0 )
7114 + $html .= '<strong class="attention">' . esc_html__('Missed schedule', 'jetpack') . '</strong>';
7115 + else
7116 + $html .= esc_html__('Scheduled', 'jetpack');
7117 + } else {
7118 + $html .= esc_html__('Last Modified', 'jetpack');
7119 + }
7120 + return $html;
7121 + }
7122 +
7123 + function column_default( $post, $column_name ) {
7124 + switch ( $column_name ) {
7125 + case 'id':
7126 + return $post->ID;
7127 + case 'post_title': // Will never happen, class method overrides.
7128 + return $post->post_title;
7129 + case 'snippet':
7130 + return wp_trim_words( $post->post_content, 55 );
7131 + case 'date': // Will never happen, class method overrides.
7132 + $d = get_option('date_format');
7133 + $t = get_option('time_format');
7134 + return get_post_modified_time( $d, 0, $post, 1 ) . ' @ ' . get_post_modified_time( $t, 0, $post, 1 );
7135 + default:
7136 + return print_r( $post, true );
7137 + }
7138 + }
7139 +}
7140 +
7141
7142 diff --git a/plugins/jetpack/modules/omnisearch/omnisearch.css b/plugins/jetpack/modules/omnisearch/omnisearch.css
7143 new file mode 100644
7144 index 0000000..f0265b7
7145 --- /dev/null
7146 +++ b/plugins/jetpack/modules/omnisearch/omnisearch.css
7147 @@ -0,0 +1,126 @@
7148 +
7149 +h2.page-title small {
7150 + font-size: 0.6em;
7151 + font-weight: 300;
7152 + font-style: italic;
7153 + opacity: 0.6;
7154 + margin-left: 0.5em;
7155 +}
7156 +
7157 +form.omnisearch-form {
7158 + position: relative;
7159 +}
7160 +
7161 +input.omnisearch {
7162 + border-radius: 0.25em;
7163 + font-size: 2.2em;
7164 + line-height: 1.25;
7165 + padding: 0.25em 2em 0.25em 0.5em;
7166 + width: 100%;
7167 +}
7168 +
7169 +.admin-color-mp6 input.omnisearch {
7170 + line-height: 1.35;
7171 +}
7172 +
7173 +input.omnisearch::-webkit-search-cancel-button {
7174 + display: none;
7175 +}
7176 +
7177 +button.omnisearch-submit {
7178 + background: transparent;
7179 + border: 0;
7180 + cursor: pointer;
7181 + display: block;
7182 + font-size: 2.45em;
7183 + padding: 0.25em 0.5em 0;
7184 + text-align: center;
7185 + position: absolute;
7186 + right: 0;
7187 + bottom: 0;
7188 +}
7189 +
7190 +.admin-color-mp6 button.omnisearch-submit {
7191 + padding: 0.3em 0.5em 0.1em;
7192 +}
7193 +
7194 +button.omnisearch-submit::before {
7195 + font-family: 'Genericons', Noticons;
7196 + content: '\f400';
7197 +}
7198 +
7199 +button.omnisearch-submit span {
7200 + display: none;
7201 +}
7202 +
7203 +#results-title,
7204 +.jump-to {
7205 + font-size: 1.2em;
7206 + line-height: 1.5;
7207 + float: left;
7208 + margin-top: 0;
7209 + padding-top: 2em;
7210 +}
7211 +
7212 +#results-title,
7213 +.jump-to strong {
7214 + font-weight: 600;
7215 +}
7216 +
7217 +.jump-to {
7218 + float: right;
7219 + text-align: right;
7220 +}
7221 +
7222 +.jump-to strong,
7223 +.jump-to a {
7224 + color: inherit;
7225 + margin-left: 0.5em;
7226 + text-decoration: none;
7227 +}
7228 +
7229 +.jump-to a:hover {
7230 + text-decoration: underline;
7231 +}
7232 +
7233 +.back-to-top {
7234 + display: block;
7235 + float: right;
7236 + margin-top: 2.5em;
7237 +}
7238 +
7239 +.omnisearch-results {
7240 +
7241 +}
7242 +
7243 +.omnisearch-results > li {
7244 + padding-top: 2.5em;
7245 +}
7246 +
7247 +.omnisearch-results > li:first-child {
7248 + padding-top: 0;
7249 +}
7250 +
7251 +.omnisearch-results .add-new-h2 {
7252 + display: inline;
7253 +}
7254 +
7255 +.wp-list-table .column-snippet {
7256 + width: 65%;
7257 +}
7258 +
7259 +.wp-list-table .column-date {
7260 + width: 15%;
7261 +}
7262 +
7263 +.comments .column-author {
7264 + width: 20%;
7265 +}
7266 +
7267 +.tablenav {
7268 + height: 0;
7269 +}
7270 +
7271 +.omnisearch-results .tablenav.top {
7272 + margin: 5px 0;
7273 +}
7274
7275 diff --git a/plugins/jetpack/modules/omnisearch/rtl/omnisearch-jetpack-rtl.css b/plugins/jetpack/modules/omnisearch/rtl/omnisearch-jetpack-rtl.css
7276 new file mode 100644
7277 index 0000000..7ddf140
7278 --- /dev/null
7279 +++ b/plugins/jetpack/modules/omnisearch/rtl/omnisearch-jetpack-rtl.css
7280 @@ -0,0 +1,37 @@
7281 +/* This file was automatically generated on Jun 19 2013 20:14:22 */
7282 +
7283 +
7284 +.wp-admin #wpwrap {
7285 + background: url('../../../_inc/images/header-clouds.png') -100% 0 repeat-x;
7286 +}
7287 +
7288 +@media print,
7289 + (-o-min-device-pixel-ratio: 5/4),
7290 + (-webkit-min-device-pixel-ratio: 1.25),
7291 + (min-resolution: 120dpi) {
7292 + #wpwrap {
7293 + background: url('../../../_inc/images/header-clouds-2x.png') 0 0 repeat-x;
7294 + background-size: 1600px 400px;
7295 + }
7296 +}
7297 +
7298 +ul#adminmenu a.wp-has-current-submenu:after,
7299 +ul#adminmenu > li.current > a.current:after {
7300 + border-left-color:#8da94c;
7301 + display: none;
7302 +}
7303 +
7304 +h2.page-title {
7305 + color: #fff;
7306 + text-shadow: 0 1px 1px rgba(0,0,0,0.5);
7307 +}
7308 +
7309 +#results-title,
7310 +.jump-to {
7311 + color: #fff;
7312 + text-shadow: 0 1px 1px rgba(0,0,0,0.5);
7313 +}
7314 +
7315 +.omnisearch-results > li:first-child > h2 {
7316 + text-shadow: none;
7317 +}
7318
7319 diff --git a/plugins/jetpack/modules/omnisearch/rtl/omnisearch-rtl.css b/plugins/jetpack/modules/omnisearch/rtl/omnisearch-rtl.css
7320 new file mode 100644
7321 index 0000000..2a5de7e
7322 --- /dev/null
7323 +++ b/plugins/jetpack/modules/omnisearch/rtl/omnisearch-rtl.css
7324 @@ -0,0 +1,128 @@
7325 +/* This file was automatically generated on Jun 19 2013 20:38:31 */
7326 +
7327 +
7328 +h2.page-title small {
7329 + font-size: 0.6em;
7330 + font-weight: 300;
7331 + font-style: italic;
7332 + opacity: 0.6;
7333 + margin-right: 0.5em;
7334 +}
7335 +
7336 +form.omnisearch-form {
7337 + position: relative;
7338 +}
7339 +
7340 +input.omnisearch {
7341 + border-radius: 0.25em;
7342 + font-size: 2.2em;
7343 + line-height: 1.25;
7344 + padding: 0.25em 0.5em 0.25em 2em;
7345 + width: 100%;
7346 +}
7347 +
7348 +.admin-color-mp6 input.omnisearch {
7349 + line-height: 1.35;
7350 +}
7351 +
7352 +input.omnisearch::-webkit-search-cancel-button {
7353 + display: none;
7354 +}
7355 +
7356 +button.omnisearch-submit {
7357 + background: transparent;
7358 + border: 0;
7359 + cursor: pointer;
7360 + display: block;
7361 + font-size: 2.45em;
7362 + padding: 0.25em 0.5em 0;
7363 + text-align: center;
7364 + position: absolute;
7365 + left: 0;
7366 + bottom: 0;
7367 +}
7368 +
7369 +.admin-color-mp6 button.omnisearch-submit {
7370 + padding: 0.3em 0.5em 0.1em;
7371 +}
7372 +
7373 +button.omnisearch-submit::before {
7374 + font-family: 'Genericons', Noticons;
7375 + content: '\f400';
7376 +}
7377 +
7378 +button.omnisearch-submit span {
7379 + display: none;
7380 +}
7381 +
7382 +#results-title,
7383 +.jump-to {
7384 + font-size: 1.2em;
7385 + line-height: 1.5;
7386 + float: right;
7387 + margin-top: 0;
7388 + padding-top: 2em;
7389 +}
7390 +
7391 +#results-title,
7392 +.jump-to strong {
7393 + font-weight: 600;
7394 +}
7395 +
7396 +.jump-to {
7397 + float: left;
7398 + text-align: left;
7399 +}
7400 +
7401 +.jump-to strong,
7402 +.jump-to a {
7403 + color: inherit;
7404 + margin-right: 0.5em;
7405 + text-decoration: none;
7406 +}
7407 +
7408 +.jump-to a:hover {
7409 + text-decoration: underline;
7410 +}
7411 +
7412 +.back-to-top {
7413 + display: block;
7414 + float: left;
7415 + margin-top: 2.5em;
7416 +}
7417 +
7418 +.omnisearch-results {
7419 +
7420 +}
7421 +
7422 +.omnisearch-results > li {
7423 + padding-top: 2.5em;
7424 +}
7425 +
7426 +.omnisearch-results > li:first-child {
7427 + padding-top: 0;
7428 +}
7429 +
7430 +.omnisearch-results .add-new-h2 {
7431 + display: inline;
7432 +}
7433 +
7434 +.wp-list-table .column-snippet {
7435 + width: 65%;
7436 +}
7437 +
7438 +.wp-list-table .column-date {
7439 + width: 15%;
7440 +}
7441 +
7442 +.comments .column-author {
7443 + width: 20%;
7444 +}
7445 +
7446 +.tablenav {
7447 + height: 0;
7448 +}
7449 +
7450 +.omnisearch-results .tablenav.top {
7451 + margin: 5px 0;
7452 +}
7453
7454 diff --git a/plugins/jetpack/modules/sharedaddy/images/kindle.png b/plugins/jetpack/modules/sharedaddy/images/kindle.png
7455 new file mode 100644
7456 index 0000000..4756d45
7457 Binary files /dev/null and b/plugins/jetpack/modules/sharedaddy/images/kindle.png differ
7458
7459 diff --git a/plugins/jetpack/modules/sharedaddy/images/kindle@××.png b/plugins/jetpack/modules/sharedaddy/images/kindle@××.png
7460 new file mode 100644
7461 index 0000000..66fa00f
7462 Binary files /dev/null and b/plugins/jetpack/modules/sharedaddy/images/kindle@××.png differ
7463
7464 diff --git a/plugins/jetpack/modules/sharedaddy/images/pocket.png b/plugins/jetpack/modules/sharedaddy/images/pocket.png
7465 new file mode 100644
7466 index 0000000..e6e1184
7467 Binary files /dev/null and b/plugins/jetpack/modules/sharedaddy/images/pocket.png differ
7468
7469 diff --git a/plugins/jetpack/modules/sharedaddy/images/pocket@××.png b/plugins/jetpack/modules/sharedaddy/images/pocket@××.png
7470 new file mode 100644
7471 index 0000000..72fdbfe
7472 Binary files /dev/null and b/plugins/jetpack/modules/sharedaddy/images/pocket@××.png differ
7473
7474 diff --git a/plugins/jetpack/modules/sharedaddy/images/smart-pocket.png b/plugins/jetpack/modules/sharedaddy/images/smart-pocket.png
7475 new file mode 100644
7476 index 0000000..69721f7
7477 Binary files /dev/null and b/plugins/jetpack/modules/sharedaddy/images/smart-pocket.png differ
7478
7479 diff --git a/plugins/jetpack/modules/sharedaddy/images/smart-pocket@××.png b/plugins/jetpack/modules/sharedaddy/images/smart-pocket@××.png
7480 new file mode 100644
7481 index 0000000..9257926
7482 Binary files /dev/null and b/plugins/jetpack/modules/sharedaddy/images/smart-pocket@××.png differ
7483
7484 diff --git a/plugins/jetpack/modules/shortcodes/bandcamp.php b/plugins/jetpack/modules/shortcodes/bandcamp.php
7485 new file mode 100644
7486 index 0000000..cfaedb9
7487 --- /dev/null
7488 +++ b/plugins/jetpack/modules/shortcodes/bandcamp.php
7489 @@ -0,0 +1,142 @@
7490 +<?php
7491 +// shortcode handler for [bandcamp], which inserts a bandcamp.com
7492 +// music player (embedded flash object)
7493 +//
7494 +// [bandcamp album=119385304]
7495 +// [bandcamp album=3462839126 bgcol=FFFFFF linkcol=4285BB size=venti]
7496 +// [bandcamp track=2446959313]
7497 +//
7498 +function shortcode_handler_bandcamp( $atts ) {
7499 + // there are no default values, but specify here anyway
7500 + // to explicitly list supported atts
7501 + $attributes = shortcode_atts( array(
7502 + 'album' => null, // integer album id
7503 + 'track' => null, // integer track id
7504 + 'size' => 'venti', // one of the supported sizes
7505 + 'bgcol' => 'FFFFFF', // hex, no '#' prefix
7506 + 'linkcol' => null, // hex, no '#' prefix
7507 + 'layout' => null, // encoded layout url
7508 + 'width' => null, // integer with optional "%"
7509 + 'height' => null, // integer with optional "%"
7510 + 'notracklist' => null, // may be string "true" (defaults false)
7511 + 'artwork' => null, // may be string "false" (defaults true)
7512 + 'theme' => null, // may be theme identifier string ("light"|"dark" so far)
7513 + 'package' => null, // integer package id
7514 + 't' => null // integer track number
7515 + ), $atts );
7516 +
7517 + $sizes = array(
7518 + 'venti' => array( 'width' => 400, 'height' => 100 ),
7519 + 'grande' => array( 'width' => 300, 'height' => 100 ),
7520 + 'grande2' => array( 'width' => 300, 'height' => 355 ),
7521 + 'grande3' => array( 'width' => 300, 'height' => 415 ),
7522 + 'tall_album' => array( 'width' => 150, 'height' => 295 ),
7523 + 'tall_track' => array( 'width' => 150, 'height' => 270 ),
7524 + 'tall2' => array( 'width' => 150, 'height' => 450 ),
7525 + 'short' => array( 'width' => 46, 'height' => 23 ),
7526 + 'large' => array( 'width' => 350, 'height' => 470 ),
7527 + 'medium' => array( 'width' => 450, 'height' => 120 ),
7528 + 'small' => array( 'width' => 350, 'height' => 42 )
7529 + );
7530 +
7531 + $sizekey = $attributes['size'];
7532 + $height = null;
7533 + $width = null;
7534 +
7535 + // Build iframe url. Args are appended as
7536 + // extra path segments for historical reasons having to
7537 + // do with an IE-only flash bug which required this URL
7538 + // to contain no querystring
7539 +
7540 + $url = "http://bandcamp.com/EmbeddedPlayer/v=2/";
7541 + if ( isset( $attributes['track'] ) ) {
7542 + $track = (int) $attributes['track'];
7543 + $url .= "track={$track}";
7544 +
7545 + if ( $sizekey == 'tall' ) {
7546 + $sizekey .= '_track';
7547 + }
7548 + } elseif ( isset( $attributes['album'] ) ) {
7549 + $album = (int) $attributes['album'];
7550 + $url .= "album={$album}";
7551 + $type = 'album';
7552 +
7553 + if ( $sizekey == 'tall' ) {
7554 + $sizekey .= '_album';
7555 + }
7556 + } else {
7557 + return "[bandcamp: shortcode must include track or album id]";
7558 + }
7559 +
7560 + // if size specified that we don't recognize, fall back on venti
7561 + if ( empty( $sizes[$sizekey] ) ) {
7562 + $sizekey = 'venti';
7563 + $attributes['size'] = 'venti';
7564 + }
7565 +
7566 + // use strict regex for digits + optional % instead of absint for height/width
7567 + // 'width' and 'height' params in the iframe url get the exact string from the shortcode
7568 + // args, whereas the inline style attribute must have "px" added to it if it has no "%"
7569 + if ( isset( $attributes['width'] ) && preg_match( "|^([0-9]+)(%)?$|", $attributes['width'], $matches ) ) {
7570 + $width = $csswidth = $attributes['width'];
7571 + if ( sizeof( $matches ) < 3 ) {
7572 + $csswidth .= "px";
7573 + }
7574 + }
7575 + if ( isset( $attributes['height'] ) && preg_match( "|^([0-9]+)(%)?$|", $attributes['height'], $matches ) ) {
7576 + $height = $cssheight = $attributes['height'];
7577 + if ( sizeof( $matches ) < 3 ) {
7578 + $cssheight .= "px";
7579 + }
7580 + }
7581 +
7582 + if ( !$height ) {
7583 + $height = $sizes[$sizekey]['height'];
7584 + $cssheight = $height . "px";
7585 + }
7586 +
7587 + if ( !$width ) {
7588 + $width = $sizes[$sizekey]['width'];
7589 + $csswidth = $width . "px";
7590 + }
7591 +
7592 + if ( isset( $attributes['layout'] ) ) {
7593 + $url .= "/layout={$attributes['layout']}";
7594 + } elseif ( isset( $attributes['size'] ) && preg_match( "|^[a-zA-Z0-9]+$|", $attributes['size'] ) ) {
7595 + $url .= "/size={$attributes['size']}";
7596 + }
7597 +
7598 + if ( isset( $attributes['bgcol'] ) && preg_match( "|^[0-9A-Fa-f]+$|", $attributes['bgcol'] ) ) {
7599 + $url .= "/bgcol={$attributes['bgcol']}";
7600 + }
7601 +
7602 + if ( isset( $attributes['linkcol'] ) && preg_match( "|^[0-9A-Fa-f]+$|", $attributes['linkcol'] ) ) {
7603 + $url .= "/linkcol={$attributes['linkcol']}";
7604 + }
7605 +
7606 + if ( isset( $attributes['package'] ) && preg_match( "|^[0-9]+$|", $attributes['package'] ) ) {
7607 + $url .= "/package={$attributes['package']}";
7608 + }
7609 +
7610 + if ( isset( $attributes['t'] ) && preg_match( "|^[0-9]+$|", $attributes['t'] ) ) {
7611 + $url .= "/t={$attributes['t']}";
7612 + }
7613 +
7614 + if ( $attributes['notracklist'] == "true" ) {
7615 + $url .= "/notracklist=true";
7616 + }
7617 +
7618 + if ( $attributes['artwork'] == "false" ) {
7619 + $url .= "/artwork=false";
7620 + }
7621 +
7622 + if ( isset( $attributes['theme'] ) && preg_match( "|^[a-zA-Z_]+$|", $attributes['theme'] ) ) {
7623 + $url .= "/theme={$attributes['theme']}";
7624 + }
7625 +
7626 + $url .= '/';
7627 +
7628 + return "<iframe width='" . esc_attr( $width ) . "' height='" . esc_attr( $height ) . "' style='position: relative; display: block; width: " . esc_attr( $csswidth ) . "; height: " . esc_attr( $cssheight ) . ";' src='" . esc_url( $url ) . "' allowtransparency='true' frameborder='0'></iframe>";
7629 +}
7630 +
7631 +add_shortcode( 'bandcamp', 'shortcode_handler_bandcamp' );
7632
7633 diff --git a/plugins/jetpack/modules/social-links.php b/plugins/jetpack/modules/social-links.php
7634 new file mode 100644
7635 index 0000000..f87b9f8
7636 --- /dev/null
7637 +++ b/plugins/jetpack/modules/social-links.php
7638 @@ -0,0 +1,10 @@
7639 +<?php
7640 +/**
7641 + * Themes must declare that they support this module by adding
7642 + * add_theme_support( 'social-links' ); on 'after_setup_theme'.
7643 + */
7644 +function jetpack_load_additional_modules() {
7645 + if ( current_theme_supports( 'social-links' ) )
7646 + require_once 'social-links/social-links.php';
7647 +}
7648 +add_action( 'init', 'jetpack_load_additional_modules' );
7649
7650 diff --git a/plugins/jetpack/modules/social-links/social-links.php b/plugins/jetpack/modules/social-links/social-links.php
7651 new file mode 100644
7652 index 0000000..b84aff9
7653 --- /dev/null
7654 +++ b/plugins/jetpack/modules/social-links/social-links.php
7655 @@ -0,0 +1,169 @@
7656 +<?php
7657 +
7658 +/**
7659 + * Social Links.
7660 + *
7661 + * This feature will only be activated for themes that declare their support.
7662 + * This can be done by adding code similar to the following during the
7663 + * 'after_setup_theme' action:
7664 + *
7665 + * add_theme_support( 'social-links', array(
7666 + * 'facebook', 'twitter', 'linkedin', 'tumblr',
7667 + * ) );
7668 + */
7669 +class Social_Links {
7670 +
7671 + /**
7672 + * The links the user set for each service.
7673 + *
7674 + * @var array
7675 + */
7676 + private $links;
7677 +
7678 + /**
7679 + * A Publicize object.
7680 + *
7681 + * @var Publicize
7682 + */
7683 + private $publicize;
7684 +
7685 + /**
7686 + * An array with all services that are supported by both Publicize and the
7687 + * currently active theme.
7688 + *
7689 + * @var array
7690 + */
7691 + private $services = array();
7692 +
7693 + /**
7694 + * Constructor.
7695 + */
7696 + public function __construct() {
7697 + $theme_support = get_theme_support( 'social-links' );
7698 +
7699 + /* An array of named arguments must be passed as the second parameter
7700 + * of add_theme_support().
7701 + */
7702 + if ( ! isset( $theme_support[0] ) || empty( $theme_support[0] ) )
7703 + return;
7704 +
7705 + $this->links = Jetpack_Options::get_option( 'social_links', array() );
7706 +
7707 + global $publicize;
7708 +
7709 + if ( is_a( $publicize, 'Publicize' ) ) {
7710 + $this->publicize = $publicize;
7711 + $this->services = array_intersect(
7712 + array_keys( $this->publicize->get_services( 'connected' ) ),
7713 + $theme_support[0]
7714 + );
7715 +
7716 + add_action( 'customize_register', array( $this, 'customize_register' ) );
7717 + add_filter( 'sanitize_option_jetpack_options', array( $this, 'sanitize_link' ) );
7718 + }
7719 +
7720 + add_filter( 'jetpack_has_social_links', array( $this, 'has_social_links' ) );
7721 + add_filter( 'jetpack_get_social_links', array( $this, 'get_social_links' ) );
7722 +
7723 + foreach ( $theme_support[0] as $service ) {
7724 + add_filter( "pre_option_jetpack-$service", array( $this, 'get_social_link_filter' ) ); // get_option( 'jetpack-service' );
7725 + add_filter( "theme_mod_jetpack-$service", array( $this, 'get_social_link_filter' ) ); // get_theme_mod( 'jetpack-service' );
7726 + }
7727 + }
7728 +
7729 + /**
7730 + * Add social link dropdown to the Customizer.
7731 + *
7732 + * @param WP_Customize_Manager $wp_customize Theme Customizer object.
7733 + */
7734 + public function customize_register( $wp_customize ) {
7735 + $wp_customize->add_section( 'jetpack_social_links', array(
7736 + 'title' => __( 'Connect', 'jetpack' ),
7737 + 'priority' => 35,
7738 + ) );
7739 +
7740 + foreach ( $this->services as $service ) {
7741 + $wp_customize->add_setting( "jetpack_options[social_links][$service]", array(
7742 + 'type' => 'option',
7743 + 'default' => '',
7744 + ) );
7745 +
7746 + $wp_customize->add_control( "jetpack-$service", array(
7747 + 'label' => $this->publicize->get_service_label( $service ),
7748 + 'section' => 'jetpack_social_links',
7749 + 'settings' => "jetpack_options[social_links][$service]",
7750 + 'type' => 'select',
7751 + 'choices' => $this->get_customize_select( $service ),
7752 + ) );
7753 + }
7754 + }
7755 +
7756 + /**
7757 + * Sanitizes social links.
7758 + *
7759 + * @param array $option The incoming values to be sanitized.
7760 + * @returns array
7761 + */
7762 + public function sanitize_link( $option ) {
7763 + foreach ( $this->services as $service ) {
7764 + if ( ! empty( $option['social_links'][ $service ] ) )
7765 + $option['social_links'][ $service ] = esc_url_raw( $option['social_links'][ $service ] );
7766 + else
7767 + unset( $option['social_links'][ $service ] );
7768 + }
7769 +
7770 + return $option;
7771 + }
7772 +
7773 + /**
7774 + * Returns whether there are any social links set.
7775 + *
7776 + * @returns bool
7777 + */
7778 + public function has_social_links() {
7779 + return ! empty( $this->links );
7780 + }
7781 +
7782 + /**
7783 + * Return available social links.
7784 + *
7785 + * @returns array
7786 + */
7787 + public function get_social_links() {
7788 + return $this->links;
7789 + }
7790 +
7791 + /**
7792 + * Short-circuits get_option and get_theme_mod calls.
7793 + *
7794 + * @param string $link The incoming value to be replaced.
7795 + * @returns string $link The social link that we've got.
7796 + */
7797 + public function get_social_link_filter( $link ) {
7798 + if ( preg_match( '/_jetpack-(.+)$/i', current_filter(), $matches ) && ! empty( $this->links[ $matches[1] ] ) )
7799 + return $this->links[ $matches[1] ];
7800 +
7801 + return $link;
7802 + }
7803 +
7804 + /**
7805 + * Puts together an array of choices for a specific service.
7806 + *
7807 + * @param string $service The social service.
7808 + * @return array An associative array with profile links and display names.
7809 + */
7810 + private function get_customize_select( $service ) {
7811 + $choices = array(
7812 + '' => __( '&mdash; Select &mdash;', 'jetpack' )
7813 + );
7814 +
7815 + $connected_services = $this->publicize->get_services( 'connected' );
7816 + if ( isset( $connected_services[ $service ] ) )
7817 + foreach ( $connected_services[ $service ] as $c )
7818 + $choices[ $this->publicize->get_profile_link( $service, $c ) ] = $this->publicize->get_display_name( $service, $c );
7819 +
7820 + return $choices;
7821 + }
7822 +}
7823 +
7824 +$jetpack_social_links = new Social_Links;
7825
7826 diff --git a/plugins/jetpack/modules/widgets/twitter-timeline.php b/plugins/jetpack/modules/widgets/twitter-timeline.php
7827 new file mode 100644
7828 index 0000000..4ab6fcb
7829 --- /dev/null
7830 +++ b/plugins/jetpack/modules/widgets/twitter-timeline.php
7831 @@ -0,0 +1,214 @@
7832 +<?php
7833 +
7834 +/*
7835 + * Based on Evolution Twitter Timeline (http://wordpress.org/extend/plugins/evolution-twitter-timeline/)
7836 + * See: https://twitter.com/settings/widgets and https://dev.twitter.com/docs/embedded-timelines for details on Twitter Timelines
7837 + */
7838 +
7839 +/**
7840 + * Register the widget for use in Appearance -> Widgets
7841 + */
7842 +add_action( 'widgets_init', 'jetpack_twitter_timeline_widget_init' );
7843 +
7844 +function jetpack_twitter_timeline_widget_init() {
7845 + register_widget( 'Jetpack_Twitter_Timeline_Widget' );
7846 +}
7847 +
7848 +class Jetpack_Twitter_Timeline_Widget extends WP_Widget {
7849 + /**
7850 + * Register widget with WordPress.
7851 + */
7852 + public function __construct() {
7853 + parent::__construct(
7854 + 'twitter_timeline',
7855 + apply_filters( 'jetpack_widget_name', esc_html__( 'Twitter Timeline', 'jetpack' ) ),
7856 + array(
7857 + 'classname' => 'widget_twitter_timeline',
7858 + 'description' => __( 'Display an official Twitter Embedded Timeline widget.', 'jetpack' )
7859 + )
7860 + );
7861 +
7862 + if ( is_active_widget( false, false, $this->id_base ) || is_active_widget( false, false, 'monster' ) ) {
7863 + wp_enqueue_script( 'twitter-widgets', '//platform.twitter.com/widgets.js', '', '', true );
7864 + }
7865 + }
7866 +
7867 + /**
7868 + * Front-end display of widget.
7869 + *
7870 + * @see WP_Widget::widget()
7871 + *
7872 + * @param array $args Widget arguments.
7873 + * @param array $instance Saved values from database.
7874 + */
7875 + public function widget( $args, $instance ) {
7876 + $instance['lang'] = substr( strtoupper( get_locale() ), 0, 2 );
7877 +
7878 + echo $args['before_widget'];
7879 +
7880 + if ( $instance['title'] )
7881 + echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ) . $args['after_title'];
7882 +
7883 + $data_attribs = array( 'widget-id', 'theme', 'link-color', 'border-color', 'chrome' );
7884 + $attribs = array( 'width', 'height', 'lang' );
7885 +
7886 + // Start tag output
7887 + echo '<a class="twitter-timeline"';
7888 +
7889 + foreach ( $data_attribs as $att ) {
7890 + if ( !empty( $instance[$att] ) ) {
7891 + if ( is_array( $instance[$att] ) )
7892 + echo ' data-' . esc_attr( $att ) . '="' . esc_attr( join( ' ', $instance['chrome'] ) ) . '"';
7893 + else
7894 + echo ' data-' . esc_attr( $att ) . '="' . esc_attr( $instance[$att] ) . '"';
7895 + }
7896 + }
7897 +
7898 + foreach ( $attribs as $att ) {
7899 + if ( !empty( $instance[$att] ) )
7900 + echo ' ' . esc_attr( $att ) . '="' . esc_attr( $instance[$att] ) . '"';
7901 + }
7902 +
7903 + echo '>' . esc_html__( 'My Tweets', 'jetpack' ) . '</a>';
7904 + // End tag output
7905 +
7906 + echo $args['after_widget'];
7907 +
7908 + do_action( 'jetpack_bump_stats_extras', 'widget', 'twitter_timeline' );
7909 + }
7910 +
7911 +
7912 + /**
7913 + * Sanitize widget form values as they are saved.
7914 + *
7915 + * @see WP_Widget::update()
7916 + *
7917 + * @param array $new_instance Values just sent to be saved.
7918 + * @param array $old_instance Previously saved values from database.
7919 + *
7920 + * @return array Updated safe values to be saved.
7921 + */
7922 + public function update( $new_instance, $old_instance ) {
7923 + $non_hex_regex = '/[^a-f0-9]/';
7924 + $instance = array();
7925 + $instance['title'] = sanitize_text_field( $new_instance['title'] );
7926 + $instance['width'] = (int) $new_instance['width'];
7927 + $instance['height'] = (int) $new_instance['height'];
7928 + $instance['width'] = ( 0 !== (int) $instance['width'] ) ? (int) $instance['width'] : 225;
7929 + $instance['height'] = ( 0 !== (int) $instance['height'] ) ? (int) $instance['height'] : 400;
7930 +
7931 + // If they entered something that might be a full URL, try to parse it out
7932 + if ( is_string( $new_instance['widget-id'] ) ) {
7933 + if ( preg_match( '#https?://twitter\.com/settings/widgets/(\d+)#s', $new_instance['widget-id'], $matches ) ) {
7934 + $new_instance['widget-id'] = $matches[1];
7935 + }
7936 + }
7937 +
7938 + $instance['widget-id'] = sanitize_text_field( $new_instance['widget-id'] );
7939 + $instance['widget-id'] = is_numeric( $instance['widget-id'] ) ? $instance['widget-id'] : '';
7940 +
7941 + foreach ( array( 'link-color', 'border-color' ) as $color ) {
7942 + $clean = preg_replace( $non_hex_regex, '', sanitize_text_field( $new_instance[$color] ) );
7943 + if ( $clean )
7944 + $instance[$color] = '#' . $clean;
7945 + }
7946 +
7947 + $instance['theme'] = 'light';
7948 + if ( in_array( $new_instance['theme'], array( 'light', 'dark' ) ) )
7949 + $instance['theme'] = $new_instance['theme'];
7950 +
7951 + $instance['chrome'] = array();
7952 + if ( isset( $new_instance['chrome'] ) ) {
7953 + foreach ( $new_instance['chrome'] as $chrome ) {
7954 + if ( in_array( $chrome, array( 'noheader', 'nofooter', 'noborders', 'noscrollbar', 'transparent' ) ) ) {
7955 + $instance['chrome'][] = $chrome;
7956 + }
7957 + }
7958 + }
7959 +
7960 + return $instance;
7961 + }
7962 +
7963 +
7964 + /**
7965 + * Back-end widget form.
7966 + *
7967 + * @see WP_Widget::form()
7968 + *
7969 + * @param array $instance Previously saved values from database.
7970 + */
7971 + public function form( $instance ) {
7972 + $defaults = array(
7973 + 'title' => esc_html__( 'Follow me on Twitter', 'jetpack' ),
7974 + 'width' => '',
7975 + 'height' => '400',
7976 + 'widget-id' => '',
7977 + 'link-color' => '#f96e5b',
7978 + 'border-color' => '#e8e8e8',
7979 + 'theme' => 'light',
7980 + 'chrome' => array(),
7981 + );
7982 +
7983 + $instance = wp_parse_args( (array) $instance, $defaults );
7984 + ?>
7985 +
7986 + <p>
7987 + <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php esc_html_e( 'Title:', 'jetpack' ); ?></label>
7988 + <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $instance['title'] ); ?>" />
7989 + </p>
7990 +
7991 + <p>
7992 + <label for="<?php echo $this->get_field_id( 'width' ); ?>"><?php esc_html_e( 'Width (px):', 'jetpack' ); ?></label>
7993 + <input class="widefat" id="<?php echo $this->get_field_id( 'width' ); ?>" name="<?php echo $this->get_field_name( 'width' ); ?>" type="text" value="<?php echo esc_attr( $instance['width'] ); ?>" />
7994 + </p>
7995 +
7996 + <p>
7997 + <label for="<?php echo $this->get_field_id( 'height' ); ?>"><?php esc_html_e( 'Height (px):', 'jetpack' ); ?></label>
7998 + <input class="widefat" id="<?php echo $this->get_field_id( 'height' ); ?>" name="<?php echo $this->get_field_name( 'height' ); ?>" type="text" value="<?php echo esc_attr( $instance['height'] ); ?>" />
7999 + </p>
8000 +
8001 + <p><small>
8002 + <?php
8003 + echo wp_kses_post(
8004 + sprintf(
8005 + __( 'You need to <a href="%1$s" target="_blank">create a widget at Twitter.com</a>, and then enter your widget id (the long number found in the URL of your widget\'s config page) in the field below. <a href="%2$s" target="_blank">Read more</a>.', 'jetpack' ),
8006 + 'https://twitter.com/settings/widgets/new/user',
8007 + 'http://support.wordpress.com/widgets/twitter-timeline-widget/'
8008 + )
8009 + );
8010 + ?>
8011 + </small></p>
8012 + <p>
8013 + <label for="<?php echo $this->get_field_id( 'widget-id' ); ?>"><?php esc_html_e( 'Widget ID:', 'jetpack' ); ?> <a href="http://support.wordpress.com/widgets/twitter-timeline-widget/#widget-id" target="_blank">( ? )</a></label>
8014 + <input class="widefat" id="<?php echo $this->get_field_id( 'widget-id' ); ?>" name="<?php echo $this->get_field_name( 'widget-id' ); ?>" type="text" value="<?php echo esc_attr( $instance['widget-id'] ); ?>" />
8015 + </p>
8016 +
8017 + <p>
8018 + <label for="<?php echo $this->get_field_id( 'chrome-noheader' ); ?>"><?php esc_html_e( 'Layout Options:', 'jetpack' ); ?></label><br />
8019 + <input type="checkbox"<?php checked( in_array( 'noheader', $instance['chrome'] ) ); ?> id="<?php echo $this->get_field_id( 'chrome-noheader' ); ?>" name="<?php echo $this->get_field_name( 'chrome' ); ?>[]" value="noheader" /> <label for="<?php echo $this->get_field_id( 'chrome-noheader' ); ?>"><?php esc_html_e( 'No Header', 'jetpack' ); ?></label><br />
8020 + <input type="checkbox"<?php checked( in_array( 'nofooter', $instance['chrome'] ) ); ?> id="<?php echo $this->get_field_id( 'chrome-nofooter' ); ?>" name="<?php echo $this->get_field_name( 'chrome' ); ?>[]" value="nofooter" /> <label for="<?php echo $this->get_field_id( 'chrome-nofooter' ); ?>"><?php esc_html_e( 'No Footer', 'jetpack' ); ?></label><br />
8021 + <input type="checkbox"<?php checked( in_array( 'noborders', $instance['chrome'] ) ); ?> id="<?php echo $this->get_field_id( 'chrome-noborders' ); ?>" name="<?php echo $this->get_field_name( 'chrome' ); ?>[]" value="noborders" /> <label for="<?php echo $this->get_field_id( 'chrome-noborders' ); ?>"><?php esc_html_e( 'No Borders', 'jetpack' ); ?></label><br />
8022 + <input type="checkbox"<?php checked( in_array( 'noscrollbar', $instance['chrome'] ) ); ?> id="<?php echo $this->get_field_id( 'chrome-noscrollbar' ); ?>" name="<?php echo $this->get_field_name( 'chrome' ); ?>[]" value="noscrollbar" /> <label for="<?php echo $this->get_field_id( 'chrome-noscrollbar' ); ?>"><?php esc_html_e( 'No Scrollbar', 'jetpack' ); ?></label><br />
8023 + <input type="checkbox"<?php checked( in_array( 'transparent', $instance['chrome'] ) ); ?> id="<?php echo $this->get_field_id( 'chrome-transparent' ); ?>" name="<?php echo $this->get_field_name( 'chrome' ); ?>[]" value="transparent" /> <label for="<?php echo $this->get_field_id( 'chrome-transparent' ); ?>"><?php esc_html_e( 'Transparent Background', 'jetpack' ); ?></label>
8024 + </p>
8025 +
8026 + <p>
8027 + <label for="<?php echo $this->get_field_id( 'link-color' ); ?>"><?php _e( 'Link Color (hex):', 'jetpack' ); ?></label>
8028 + <input class="widefat" id="<?php echo $this->get_field_id( 'link-color' ); ?>" name="<?php echo $this->get_field_name( 'link-color' ); ?>" type="text" value="<?php echo esc_attr( $instance['link-color'] ); ?>" />
8029 + </p>
8030 +
8031 + <p>
8032 + <label for="<?php echo $this->get_field_id( 'border-color' ); ?>"><?php _e( 'Border Color (hex):', 'jetpack' ); ?></label>
8033 + <input class="widefat" id="<?php echo $this->get_field_id( 'border-color' ); ?>" name="<?php echo $this->get_field_name( 'border-color' ); ?>" type="text" value="<?php echo esc_attr( $instance['border-color'] ); ?>" />
8034 + </p>
8035 +
8036 + <p>
8037 + <label for="<?php echo $this->get_field_id( 'theme' ); ?>"><?php _e( 'Timeline Theme:', 'jetpack' ); ?></label>
8038 + <select name="<?php echo $this->get_field_name( 'theme' ); ?>" id="<?php echo $this->get_field_id( 'theme' ); ?>" class="widefat">
8039 + <option value="light"<?php selected( $instance['theme'], 'light' ); ?>><?php esc_html_e( 'Light', 'jetpack' ); ?></option>
8040 + <option value="dark"<?php selected( $instance['theme'], 'dark' ); ?>><?php esc_html_e( 'Dark', 'jetpack' ); ?></option>
8041 + </select>
8042 + </p>
8043 + <?php
8044 + }
8045 +}