· 8 years ago · Jan 10, 2018, 03:08 PM
1<?php
2
3class BD_Shortcodes extends KokenPlugin {
4
5 function __construct()
6 {
7 $this->register_shortcode('koken_photo', 'koken_media');
8 $this->register_shortcode('koken_video', 'koken_media');
9 $this->register_shortcode('koken_oembed', 'koken_oembed');
10 $this->register_shortcode('koken_slideshow', 'koken_slideshow');
11 $this->register_shortcode('koken_upload', 'koken_upload');
12 $this->register_shortcode('koken_code', 'koken_code');
13 $this->register_shortcode('koken_contact_form', 'koken_contact_form');
14
15 $this->register_hook('site.url', 'koken_contact_submit');
16 }
17
18 function koken_contact_submit()
19 {
20 if (isset($_POST) && isset($_POST['koken_contact_form']))
21 {
22 if (!empty($_POST['k-contact-field-dummy']))
23 {
24 header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500);
25 exit;
26 }
27 else if (!empty($_POST['g-recaptcha-response']) && !empty($_POST['g-recaptcha-key']))
28 {
29 $gRecaptchaResponse = $_POST['g-recaptcha-response'];
30 $secret_key = $_POST['g-recaptcha-key'];
31
32 $key = Shutter::get_encryption_key();
33 $secret_key = base64_decode($secret_key);
34 $iv = substr($secret_key, 0, 16);
35 $secret_key = substr($secret_key, 16);
36 $secret_key = openssl_decrypt($secret_key, 'AES-256-CTR', $key, 0, $iv);
37
38 if (isset($secret_key))
39 {
40 require(Koken::$root_path . '/app/application/libraries/ReCaptcha/autoload.php');
41 $recaptcha = new \ReCaptcha\ReCaptcha($secret_key);
42 $resp = $recaptcha->verify($gRecaptchaResponse);
43
44 if (!$resp->isSuccess()) {
45 header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500);
46 exit;
47 }
48 }
49 }
50 else if (!isset($_POST['g-recaptcha-response'], $_POST['g-recaptcha-key']) && !isset($_POST['k-contact-field-dummy']))
51 {
52 header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500);
53 exit;
54 }
55
56 // convert unicode escaped to utf-8
57 $labels = preg_replace_callback('/\\\\u([0-9a-fA-F]{4})/', function ($match) {
58 return mb_convert_encoding(pack('H*', $match[1]), 'UTF-8', 'UCS-2BE');
59 }, $_POST['labels']);
60
61 // stripslashes required here for PHP 5.3 weirdness
62 $labels = json_decode(stripslashes($labels), true);
63 $separator = str_repeat('–', 30);
64
65 $msg = array("You have received a new Koken contact form submission. The details of the submission are below.");
66 foreach($labels as $index => $label)
67 {
68 $key = 'k-contact-field-' . $index;
69 $value = isset($_POST[$key]) ? $_POST[$key] : 'No';
70
71 if (empty($value)) continue;
72
73 $msg[] = "$label\n$separator\n$value";
74 }
75
76 $msg = join("\n\n\n", $msg);
77
78 $from = $_POST[$_POST['from_field']];
79
80 $this->deliver_email($from, $from, '[' . $_SERVER['HTTP_HOST'] . '] Koken Contact Form Submission', $msg);
81
82 exit;
83 }
84 }
85
86 function koken_contact_form($attr)
87 {
88 $id = 'k-contact-form-' . md5(uniqid('', true));
89 $out = <<<HTML
90<figure class="k-content-embed">
91 <p class="k-contact-form-success" style="display: none">{$attr['success_message']}</p>
92 <koken:form id="$id" class="k-contact-form">
93 <input type="hidden" name="koken_contact_form" value="1" />
94HTML;
95
96 $required = array();
97 $labels = array();
98
99 $fromEmail = false;
100
101 foreach(json_decode($attr['fields']) as $index => $field)
102 {
103 $labels[] = htmlentities($field[0], ENT_QUOTES);
104 $name = 'k-contact-field-' . $index;
105 $type = $field[1];
106
107 $field_id = $id . '-' . $name;
108
109 if ($field[2]) {
110 $required[] = $name;
111 }
112
113 if ($type === 'email' && !$fromEmail)
114 {
115 $fromEmail = $name;
116 }
117
118 if ($type === 'textarea')
119 {
120 $input = '<textarea id="' . $field_id . '" name="' . $name . '" rows="10"></textarea>';
121 }
122 else
123 {
124 $input = '<input id="' . $field_id . '" name="' . $name . '" type="' . $type . ($type === 'checkbox' ? '" value="Yes"' : '"') . ' />';
125 }
126
127 $required_class = $field[2] ? ' k-contact-form-required-field' : '';
128
129 $before_label = $after_label = '';
130
131 if ($type === 'checkbox')
132 {
133 $before_label = $input;
134 }
135 else
136 {
137 $after_label = $input;
138 }
139
140 $out .= <<<HTML
141<fieldset class="k-contact-form-$type-field{$required_class}">
142 {$before_label}
143 <label for="$field_id">{$field[0]}</label>
144 {$after_label}
145</fieldset>
146HTML;
147 }
148
149 list($recaptcha, $site_key, $secret_key) = json_decode($attr['recaptcha']);
150
151 if ($recaptcha)
152 {
153 $key = Shutter::get_encryption_key();
154 $iv = openssl_random_pseudo_bytes(16);
155 $secret_key = openssl_encrypt($secret_key, 'AES-256-CTR', $key, 0, $iv);
156 $secret_key = base64_encode($iv . $secret_key);
157 $required[] = 'g-recaptcha-response';
158
159 $out .= <<<HTML
160<script src='https://www.google.com/recaptcha/api.js'></script>
161<fieldset class="k-contact-form-captcha-field k-contact-form-required-field">
162 <label>Captcha</label>
163 <div class="g-recaptcha" data-sitekey="{$site_key}"></div>
164 <input type="hidden" name="g-recaptcha-key" value="{$secret_key}" />
165</fieldset>
166HTML;
167 }
168 else
169 {
170 $out .= <<<HTML
171<input type="text" name="k-contact-field-dummy" style="display:none" />
172HTML;
173 }
174
175 $required = json_encode($required);
176 $labels = json_encode($labels);
177
178 $out .= <<<HTML
179<fieldset class="k-contact-form-submit">
180 <input type="hidden" name="labels" value='$labels' />
181 <input type="hidden" name="from_field" value="$fromEmail" />
182 <button type="submit">{$attr['button_label']}</button>
183</fieldset>
184
185</koken:form>
186</figure>
187
188<script>
189 $(document).off('submit.contact').on('submit.contact', '#$id', function() {
190 var form = $(this);
191 var button = form.find('button[type="submit"]');
192 var required = $required;
193 var valid = true;
194
195 button.attr('disabled', true);
196
197 form.find('.k-contact-form-error').removeClass('k-contact-form-error');
198
199 $.each(required, function(i, name) {
200 var input = form.find('[name="' + name + '"]');
201 if (!input.val().length) {
202 input.parents('fieldset').addClass('k-contact-form-error');
203 if (valid) {
204 input.focus();
205 }
206 valid = false;
207 }
208 });
209
210
211 if (valid) {
212 form.addClass('k-contact-form-processing');
213
214 $.post(location.href, form.serialize(), function() {
215 form.parent().find('.k-contact-form-success').show();
216 form.hide();
217 });
218 } else {
219 button.attr('disabled', false);
220 }
221
222 return false;
223 });
224</script>
225HTML;
226
227 return $out;
228 }
229
230 function koken_oembed($attr)
231 {
232 if (!isset($attr['url']) || !isset($attr['endpoint'])) { return ''; }
233
234 $endpoint = $attr['endpoint'];
235
236 if (strpos($endpoint, 'maxwidth=') === false)
237 {
238 if (strpos($endpoint, '?') !== false)
239 {
240 $endpoint .= '&';
241 }
242 else
243 {
244 $endpoint .= '?';
245 }
246
247 $endpoint .= 'maxwidth=1920&maxheight=1080';
248 }
249
250 if (strpos($endpoint, '?') !== false)
251 {
252 $endpoint .= '&';
253 }
254 else
255 {
256 $endpoint .= '?';
257 }
258
259 $info = Shutter::get_oembed($endpoint . 'url=' . $attr['url']);
260
261 if (isset($info['html']))
262 {
263 $html = preg_replace('/<iframe/', '<iframe style="display:none"', $info['html']);
264 }
265 else if (isset($info['url'])) {
266 $html = '<img src="' . $info['url'] . '" />';
267 }
268 else
269 {
270 return '';
271 }
272 return '<figure class="k-content-embed"><div class="k-content">' . $html . '</div></figure>';
273 }
274
275 function koken_media($attr)
276 {
277 if (!isset($attr['id'])) { return ''; }
278
279 if ($attr['media_type'] === 'image')
280 {
281 $tag = 'img lazy="true"';
282
283 if (isset($attr['height']) && is_numeric($attr['height']))
284 {
285 $tag .= ' height="' . $attr['height'] . '"';
286 }
287 }
288 else
289 {
290 $tag = 'video';
291 }
292
293 $fig_style = '';
294 if (isset($attr['width']) && is_numeric($attr['width']))
295 {
296 $tag .= ' width="' . $attr['width'] . '"';
297 $fig_style = ' style="width:' . $attr['width'] . 'px;"';
298 }
299
300 $text = '';
301 if (!isset($attr['caption']) || $attr['caption'] !== 'none')
302 {
303 if (!isset($attr['caption']) || $attr['caption'] === 'both')
304 {
305 $text .= '<koken:not empty="content.title && content.caption">';
306 }
307 else
308 {
309 $text .= '<koken:not empty="content.' . $attr['caption'] . '">';
310 }
311 $text .= '<figcaption class="k-content-text">';
312 if (!isset($attr['caption']) || $attr['caption'] !== 'caption')
313 {
314 $text .= '<koken:not empty="content.title"><span class="k-content-title">{{ content.title }}</span></koken:if>';
315 }
316 if (!isset($attr['caption']) || $attr['caption'] !== 'title')
317 {
318 $text .= '<koken:not empty="content.caption"><span class="k-content-caption">{{ content.caption }}</span></koken:if>';
319 }
320 $text .= '</figcaption></koken:not>';
321 }
322
323 $link_pre = $link_post = $context_param = '';
324
325 if (isset($attr['link']) && $attr['link'] !== 'none')
326 {
327 if ($attr['link'] === 'detail' || $attr['link'] === 'lightbox')
328 {
329 $link_pre = '<koken:link' . ( $attr['link'] === 'lightbox' ? ' lightbox="true"': '' ) . '>';
330 $link_post = '</koken:link>';
331 }
332 else if ($attr['link'] === 'album')
333 {
334 $context_param = " filter:context=\"{$attr['album']}\"";
335 $link_pre = '<koken:link data="context.album">';
336 $link_post = '</koken:link>';
337 }
338 else
339 {
340 $link_pre = '<a href="' . $attr['custom_url'] . '">';
341 $link_post = '</a>';
342 }
343 }
344
345 return <<<HTML
346<figure class="k-content-embed" ${fig_style}>
347 <koken:load source="content" filter:id="{$attr['id']}"$context_param>
348 <div class="k-content">
349 $link_pre
350 <koken:$tag />
351 $link_post
352 </div>
353 $text
354 </koken:load>
355</figure>
356HTML;
357
358 }
359
360 function koken_upload($attr)
361 {
362 $text = '';
363 $src = $attr['filename'];
364 $link_pre = $link_post = '';
365
366 if (isset($attr['link']) && !empty($attr['link']))
367 {
368 $link_pre = '<a href="' . $attr['link'] . '"' . ( isset($attr['target']) && $attr['target'] !== 'none' ? ' target="_blank"' : '' ) . '>';
369 $link_post = '</a>';
370 }
371
372 if (isset($attr['title']) && !empty($attr['title']))
373 {
374 $text .= '<span class="k-content-title">' . $attr['title'] . '</span>';
375 }
376
377 if (isset($attr['caption']) && !empty($attr['caption']))
378 {
379 $text .= '<span class="k-content-caption">' . $attr['caption'] . '</span>';
380 }
381
382 if (!empty($text))
383 {
384 $text = "<figcaption class=\"k-content-text\">$text</figcaption>";
385 }
386
387 if (strpos($src, 'http://') === 0)
388 {
389 return <<<HTML
390<figure class="k-content-embed">
391 <div class="k-content">
392 $link_pre
393 <img src="$src" style="max-width:100%" />
394 $link_post
395 </div>
396 $text
397</figure>
398HTML;
399 }
400 else
401 {
402 return <<<HTML
403<figure class="k-content-embed">
404 <koken:load source="content" filter:custom="$src">
405 <div class="k-content">
406 $link_pre
407 <koken:img lazy="true" />
408 $link_post
409 </div>
410 $text
411 </koken:load>
412</figure>
413HTML;
414 }
415
416 }
417
418 function koken_code($attr)
419 {
420 if (isset($attr['code']))
421 {
422 return $attr['code'];
423 }
424 else
425 {
426 return '';
427 }
428 }
429
430 function koken_slideshow($attr)
431 {
432 $rand = 'p' . md5(uniqid(function_exists('mt_rand') ? mt_rand() : rand(), true));
433
434 if (!isset($attr['link_to']))
435 {
436 $attr['link_to'] = 'default';
437 }
438
439 $attr['link_to'] = 'link_to="' . $attr['link_to'] . '"';
440
441 if (isset($attr['content']))
442 {
443 $path = '/content/' . $attr['content'];
444 }
445 else if (isset($attr['album']))
446 {
447 $path = '/albums/' . $attr['album'] . '/content';
448 }
449
450 $text = '';
451 if (isset($attr['caption']) && $attr['caption'] !== 'none')
452 {
453 $text .= '<figcaption id="' . $rand .'_text" class="k-content-text">';
454 if ($attr['caption'] !== 'caption')
455 {
456 $text .= '<span class="k-content-title"> </span>';
457 }
458 if ($attr['caption'] !== 'title')
459 {
460 $text .= '<span class="k-content-caption"> </span>';
461 }
462 $text .= '</figcaption>';
463 $text .= <<<JS
464 <script>
465 $rand.on( 'transitionstart', function(e) {
466 var title = $('#{$rand}_text').find('.k-content-title'),
467 caption = $('#{$rand}_text').find('.k-content-caption');
468
469 if (title) {
470 title.text(e.data.title || e.data.filename);
471 }
472
473 if (caption) {
474 caption.html(e.data.caption);
475 }
476 });
477 </script>
478JS;
479 }
480
481 return <<<HTML
482<figure class="k-content-embed">
483 <div class="k-content">
484 <koken:pulse jsvar="$rand" data_from_url="$path" size="auto" {$attr['link_to']} group="essays" />
485 </div>
486 $text
487</figure>
488HTML;
489
490 }
491}