PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 15.9-a.7
Jetpack – WP Security, Backup, Speed, & Growth v15.9-a.7
15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / modules / shortcodes / googleapps.php
jetpack / modules / shortcodes Last commit date
css 2 weeks ago images 1 year ago img 4 weeks ago js 6 months ago archiveorg-book.php 6 months ago archiveorg.php 6 months ago archives.php 2 weeks ago bandcamp.php 6 months ago brightcove.php 5 months ago cartodb.php 6 months ago class.filter-embedded-html-objects.php 6 months ago codepen.php 6 months ago crowdsignal.php 5 months ago dailymotion.php 6 months ago descript.php 6 months ago facebook.php 6 months ago flatio.php 6 months ago flickr.php 5 months ago getty.php 6 months ago gist.php 6 months ago googleapps.php 6 months ago googlemaps.php 3 weeks ago googleplus.php 6 months ago gravatar.php 6 months ago houzz.php 6 months ago inline-pdfs.php 6 months ago instagram.php 6 months ago kickstarter.php 6 months ago mailchimp.php 5 months ago medium.php 6 months ago mixcloud.php 6 months ago others.php 6 months ago pinterest.php 6 months ago presentations.php 6 months ago quiz.php 6 months ago recipe.php 6 months ago scribd.php 6 months ago shortcode-utils.php 6 months ago sitemap.php 6 months ago slideshare.php 6 months ago slideshow.php 4 weeks ago smartframe.php 6 months ago soundcloud.php 6 months ago spotify.php 6 months ago ted.php 6 months ago tweet.php 6 months ago twitchtv.php 6 months ago twitter-timeline.php 6 months ago twitter.php 6 months ago unavailable.php 6 months ago untappd-menu.php 6 months ago upcoming-events.php 6 months ago ustream.php 6 months ago videopress.php 6 months ago vimeo.php 1 week ago vine.php 6 months ago vr.php 1 week ago wufoo.php 6 months ago youtube.php 3 months ago
googleapps.php
263 lines
1 <?php
2 /**
3 * Google Docs and Google Calendar Shortcode
4 *
5 * Presentation:
6 * <iframe src="https://docs.google.com/present/embed?id=dhfhrphh_123drp8s65c&interval=15&autoStart=true&loop=true&size=l" frameborder="0" width="700" height="559"></iframe>
7 * <iframe src="https://docs.google.com/presentation/embed?id=13ItX4jV0SOSdr-ZjHarcpTh9Lr4omfsHAp87jpxv8-0&start=false&loop=false&delayms=3000" frameborder="0" width="960" height="749" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>
8 *
9 * Document:
10 * <iframe src="https://docs.google.com/document/pub?id=1kDatklacdZ_tZUOpWtt_ONzY97Ldj2zFcuO9LBY2Ln4&amp;embedded=true"></iframe>
11 * <iframe src="https://docs.google.com/document/d/1kDatklacdZ_tZUOpWtt_ONzY97Ldj2zFcuO9LBY2Ln4/pub?embedded=true"></iframe>
12 * <iframe src="https://docs.google.com/document/d/e/2PACX-1vRkpIdasKL-eKXDjJgpEONduUspZTz0YmKaajfie0eJYnzikuyusuG1_V8X8T9XflN9l8A1oCM2sgEA/pub?embedded=true"></iframe>
13 *
14 * External document:
15 * <iframe width=100% height=560px frameborder=0 src=https://docs.google.com/a/pranab.in/viewer?a=v&pid=explorer&chrome=false&embedded=true&srcid=1VTMwdgGiDMt8MCr75-YkQP-4u9WmEp1Qvf6C26KYBgFilxU2qndpd-VHhBIn&hl=en></iframe>
16 *
17 * Spreadsheet Form:
18 * <iframe src="https://spreadsheets.google.com/embeddedform?formkey=dEVOYnMzZG5jMUpGbjFMYjFYNVB3NkE6MQ" width="760" height="710" frameborder="0" marginheight="0" marginwidth="0">Loading...</iframe>
19 *
20 * Spreadsheet Widget:
21 * <iframe width='500' height='300' frameborder='0' src='https://spreadsheets1.google.com/a/petedavies.com/pub?hl=en&hl=en&key=0AjSij7nlnXvKdHNsNjRSWG12YmVfOEFwdlMxQ3J1S1E&single=true&gid=0&output=html&widget=true'></iframe>
22 * <iframe width='500' height='300' frameborder='0' src='https://spreadsheets.google.com/spreadsheet/pub?hl=en&hl=en&key=0AhInIwfvYrIUdGJiTXhtUEhBSFVPUzdRZU5OMDlqdnc&output=html&widget=true'></iframe>
23 *
24 * Calendar:
25 * <iframe src="https://www.google.com/calendar/embed?src=serjant%40gmail.com&ctz=Europe/Sofia" style="border: 0" width="800" height="600" frameborder="0" scrolling="no"></iframe>
26 * <iframe src="http://www.google.com/calendar/hosted/belcastro.com/embed?src=n8nr8sd6v9hnus3nmlk7ed1238%40group.calendar.google.com&ctz=Europe/Zurich" style="border: 0" width="800" height="600" frameborder="0" scrolling="no"></iframe>
27 *
28 * Customized calendar:
29 * <iframe src="https://www.google.com/calendar/embed?title=asdf&amp;showTitle=0&amp;showNav=0&amp;showDate=0&amp;showPrint=0&amp;showTabs=0&amp;showCalendars=0&amp;
30 * showTz=0&amp;mode=AGENDA&amp;height=300&amp;wkst=2&amp;hl=fi&amp;bgcolor=%23ffcccc&amp;src=m52gdmbgelo3itf00u1v44g0ns%40group.calendar.google.com&amp;color=%234E5D6C&amp;
31 * src=serjant%40gmail.com&amp;color=%235229A3&amp;ctz=Europe%2FRiga" style=" border:solid 1px #777 " width="500" height="300" frameborder="0" scrolling="no"></iframe>
32 *
33 * Generic
34 * <iframe src="https://docs.google.com/file/d/0B0SIdZW7iu-zX1RWREJpMXVHZVU/preview" width="640" height="480"></iframe>
35 *
36 * @package automattic/jetpack
37 */
38
39 if ( ! defined( 'ABSPATH' ) ) {
40 exit( 0 );
41 }
42
43 if ( jetpack_shortcodes_should_hook_pre_kses() ) {
44 add_filter( 'pre_kses', 'googleapps_embed_to_shortcode' );
45 }
46
47 add_shortcode( 'googleapps', 'googleapps_shortcode' );
48
49 /**
50 * Reverse iframe embed to shortcode mapping HTML attributes to shortcode attributes.
51 *
52 * @since 4.5.0
53 *
54 * @param string $content Post content.
55 *
56 * @return mixed
57 */
58 function googleapps_embed_to_shortcode( $content ) {
59 if (
60 ! is_string( $content )
61 || false === stripos( $content, '<iframe' )
62 && false === stripos( $content, '.google.com' )
63 ) {
64 return $content;
65 }
66
67 $regexp = '#<iframe((?:\s+\w+="[^"]*")*?)\s*src="https?://(docs|drive|spreadsheets\d*|calendar|www)*\.google\.com/(?!maps)([-\w\./]+)(?:\?)?([^"]+)?"\s*((?:\s+\w+="[^"]*")*?)>.*?</iframe>#i';
68 $regexp_ent = str_replace( '&amp;#0*58;', '&amp;#0*58;|&#0*58;', htmlspecialchars( $regexp, ENT_NOQUOTES ) );
69 $regexp_squot = str_replace( '"', "'", $regexp );
70 $regexp_ent_squot = str_replace( '"', "'", $regexp_ent );
71 $regexp_noquot = '!<iframe(.*?)src=https://(docs|drive)\.google\.com/[-\.\w/]*?(viewer)\?(.*?)>(.*?)</iframe>!';
72 $regexp_ent_noquot = str_replace( '&amp;#0*58;', '&amp;#0*58;|&#0*58;', htmlspecialchars( $regexp_noquot, ENT_NOQUOTES ) );
73
74 foreach ( compact( 'regexp', 'regexp_ent', 'regexp_squot', 'regexp_ent_squot', 'regexp_noquot', 'regexp_ent_noquot' ) as $reg => $regexp ) {
75 if ( ! preg_match_all( $regexp, $content, $matches, PREG_SET_ORDER ) ) {
76 continue;
77 }
78
79 foreach ( $matches as $match ) {
80 $params = $match[1] . $match[5];
81 if ( in_array( $reg, array( 'regexp_ent', 'regexp_ent_squot' ), true ) ) {
82 $params = html_entity_decode( $params, ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 );
83 }
84
85 $params = wp_kses_hair( $params, array( 'http' ) );
86
87 $width = 0;
88 $height = 0;
89
90 if ( isset( $params['width'] ) ) {
91 $width = (int) $params['width']['value'];
92 }
93
94 if ( isset( $params['height'] ) ) {
95 $height = (int) $params['height']['value'];
96 }
97
98 // allow the user to specify width greater than 200 inside text widgets.
99 if (
100 $width > 400
101 // We don't need to check a nonce here. A nonce is already checked "further up" in most code paths.
102 // In the case where no nonce is ever checked, setting this $_POST parameter doesn't do anything the submitter couldn't already do (set the width/height).
103 && isset( $_POST['widget-text'] ) // phpcs:ignore WordPress.Security.NonceVerification.Missing
104 ) {
105 $width = 200;
106 $height = 200;
107 }
108
109 $attributes = '';
110 if ( isset( $params['width'] ) && '100%' === $params['width']['value'] ) {
111 $width = '100%';
112 }
113
114 if ( $width ) {
115 $attributes = ' width="' . $width . '"';
116 }
117
118 if ( $height ) {
119 $attributes .= ' height="' . $height . '"';
120 }
121
122 $domain = 'spreadsheets';
123 if ( in_array( $match[2], array( 'docs', 'drive', 'www', 'calendar' ), true ) ) {
124 $domain = $match[2];
125 }
126
127 // Make sure this is actually something that the shortcode supports. If it's not, leave the HTML alone.
128 if ( ! googleapps_validate_domain_and_dir( $domain, $match[3] ) ) {
129 continue;
130 }
131
132 /** This action is documented in modules/widgets/social-media-icons.php */
133 do_action( 'jetpack_bump_stats_extras', 'html_to_shortcode', googleapps_service_name( $domain, $match[3] ) );
134
135 $content = str_replace( $match[0], '[googleapps domain="' . $domain . '" dir="' . $match[3] . '" query="' . esc_attr( $match[4] ) . '"' . $attributes . ' /]', $content );
136 }
137 }
138
139 return $content;
140 }
141
142 /**
143 * Parse shortcode attributes and output a Google Docs embed.
144 *
145 * @since 4.5.0
146 *
147 * @param array $atts Shortcode attributes.
148 *
149 * @return string
150 */
151 function googleapps_shortcode( $atts ) {
152 global $content_width;
153
154 $attr = shortcode_atts(
155 array(
156 'width' => '100%',
157 'height' => '560',
158 'domain' => 'docs',
159 'dir' => 'document',
160 'query' => '',
161 'src' => '',
162 ),
163 $atts
164 );
165
166 if ( is_numeric( $content_width ) && $content_width > 0 && is_numeric( $attr['width'] ) && $attr['width'] > $content_width ) {
167 $attr['width'] = $content_width;
168 }
169
170 if ( is_numeric( $content_width ) && $content_width > 0 && '560' === $attr['height'] ) {
171 $attr['height'] = floor( $content_width * 3 / 4 );
172 }
173
174 if ( isset( $atts[0] ) && $atts[0] ) {
175 $attr['src'] = $atts[0];
176 }
177
178 if ( $attr['src'] && preg_match( '!https?://(docs|drive|spreadsheets\d*|calendar|www)*\.google\.com/([-\w\./]+)\?([^"]+)!', $attr['src'], $matches ) ) {
179 $attr['domain'] = $matches[1];
180 $attr['dir'] = $matches[2];
181 parse_str( htmlspecialchars_decode( $matches[3], ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 ), $query_ar );
182 $query_ar['chrome'] = 'false';
183 $query_ar['embedded'] = 'true';
184 $attr['query'] = http_build_query( $query_ar );
185 }
186
187 if ( ! googleapps_validate_domain_and_dir( $attr['domain'], $attr['dir'] ) ) {
188 return '<!-- Unsupported URL -->';
189 }
190
191 $attr['query'] = $attr['dir'] . '?' . $attr['query'];
192
193 /** This action is documented in modules/widgets/social-media-icons.php */
194 do_action( 'jetpack_bump_stats_extras', 'embeds', googleapps_service_name( $attr['domain'], $attr['dir'] ) );
195
196 return sprintf(
197 '<iframe src="%s" frameborder="0" width="%s" height="%s" marginheight="0" marginwidth="0" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>',
198 esc_url( 'https://' . $attr['domain'] . '.google.com/' . $attr['query'] ),
199 esc_attr( $attr['width'] ),
200 esc_attr( $attr['height'] )
201 );
202 }
203
204 /**
205 * Check that the domain blogs to a Google Apps domain.
206 *
207 * @since 4.5.0
208 *
209 * @param string $domain Google subdomain.
210 * @param string $dir Subdirectory of the shared URL.
211 *
212 * @return bool
213 */
214 function googleapps_validate_domain_and_dir( $domain, $dir ) {
215 if ( ! in_array( $domain, array( 'docs', 'drive', 'www', 'spreadsheets', 'calendar' ), true ) ) {
216 return false;
217 }
218
219 // Calendars.
220 if ( ( 'www' === $domain || 'calendar' === $domain ) && ! str_starts_with( $dir, 'calendar/' ) ) {
221 return false;
222 }
223
224 // Docs.
225 if ( in_array( $domain, array( 'docs', 'drive' ), true ) && ! preg_match( '![-\.\w/]*(presentation/embed|presentation/d/(.*)|present/embed|document/pub|spreadsheets/d/(.*)|document/d/(e/)?[\w-]+/pub|file/d/[\w-]+/preview|viewer|forms/d/(.*)/viewform|spreadsheet/\w+)$!', $dir ) ) {
226 return false;
227 }
228
229 // Spreadsheets.
230 if ( 'spreadsheets' === $domain && ! preg_match( '!^([-\.\w/]+/pub|[-\.\w/]*embeddedform)$!', $dir ) ) {
231 return false;
232 }
233
234 return true;
235 }
236
237 /**
238 * Get the name of the service we'll be embedding.
239 *
240 * @since 4.5.0
241 *
242 * @param string $domain Google subdomain.
243 * @param string $dir Subdirectory of the shared URL.
244 *
245 * @return string
246 */
247 function googleapps_service_name( $domain, $dir ) {
248 switch ( $domain ) {
249 case 'drive':
250 case 'docs':
251 $service_name = ( 'present/embed' === $dir ) ? 'googledocs_presentation' : 'googledocs_document';
252 break;
253 case 'spreadsheets':
254 $service_name = ( 'embeddedform' === $dir ) ? 'googledocs_form' : 'googledocs_spreadsheet';
255 break;
256 case 'calendar':
257 default:
258 $service_name = 'google_calendar';
259 }
260
261 return $service_name;
262 }
263