• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

Revisiond5b3306ee8e913446ddef831a08a05a04527c4b2 (tree)
Time2018-03-22 02:14:44
Authorumorigu <umorigu@gmai...>
Commiterumorigu

Log Message

BugTrack/2247 External link cushion page - Control Referer etc.

* New plugin: external_link.inc.php
* New config: $external_link_cushion_page, $external_link_cushion

You can set "internal domains", on these host, you don't need to
see cushion page.

Change Summary

Incremental Difference

--- a/en.lng.php
+++ b/en.lng.php
@@ -446,3 +446,11 @@ $_loginform_messages = array(
446446 'login' => 'Log in',
447447 'invalid_username_or_password' => 'The username or password you entered is incorrect'
448448 );
449+
450+///////////////////////////////////////
451+// external_link.inc.php
452+$_external_link_messages = array(
453+ 'page_title' => 'External link: %s',
454+ 'desc' => 'The selected URL is not the contents of this site.',
455+ 'wait_n_seconds' => 'It will move to the page automatically after %s seconds.',
456+);
Binary files /dev/null and b/image/external-link.png differ
--- a/ja.lng.php
+++ b/ja.lng.php
@@ -448,3 +448,11 @@ $_loginform_messages = array(
448448 'login' => 'ログイン',
449449 'invalid_username_or_password' => 'ユーザー名またはパスワードが違います'
450450 );
451+
452+///////////////////////////////////////
453+// external_link.inc.php
454+$_external_link_messages = array(
455+ 'page_title' => '外部リンク: %s',
456+ 'desc' => '選択されたURLは本サイトのコンテンツではありません。',
457+ 'wait_n_seconds' => '%s 秒後に自動的に移動します。',
458+);
--- a/lib/html.php
+++ b/lib/html.php
@@ -219,6 +219,7 @@ function _decorate_Nth_word($matches)
219219 function get_html_scripting_data()
220220 {
221221 global $ticket_link_sites, $plugin;
222+ global $external_link_cushion_page, $external_link_cushion;
222223 if (!isset($ticket_link_sites) || !is_array($ticket_link_sites)) {
223224 return '';
224225 }
@@ -261,11 +262,21 @@ EOS;
261262 $ticketlink_data = <<<EOS
262263 <input type="hidden" class="ticketlink-def" value="$h_ticket_link_sites" />
263264 EOS;
265+ // External link cushion page
266+ $external_link_cushion_data = '';
267+ if ($external_link_cushion_page) {
268+ $h_cushion = htmlsc(json_encode($external_link_cushion,
269+ JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
270+ $external_link_cushion_data = <<<EOS
271+<input type="hidden" class="external-link-cushion" value="$h_cushion" />
272+EOS;
273+ }
264274 $data = <<<EOS
265275 <div id="pukiwiki-site-properties" style="display:none;">
266276 $site_props
267277 $plugin_prop
268278 $ticketlink_data
279+$external_link_cushion_data
269280 </div>
270281 EOS;
271282 return $data;
--- a/pukiwiki.ini.php
+++ b/pukiwiki.ini.php
@@ -314,6 +314,26 @@ $ticket_link_sites = array(
314314 );
315315
316316 /////////////////////////////////////////////////
317+// Show External Link Cushion Page
318+// 0: Disabled
319+// 1: Enabled
320+$external_link_cushion_page = 0;
321+$external_link_cushion = array(
322+ // Wait N seconds before jumping to an external site
323+ 'wait_seconds' => 5,
324+ // Internal site domain list
325+ 'internal_domains' => array(
326+ 'localhost',
327+ // '*.example.com',
328+ ),
329+ // Don't show extenal link icons on these domains
330+ 'silent_external_domains' => array(
331+ 'pukiwiki.osdn.jp',
332+ 'pukiwiki.example.com',
333+ ),
334+);
335+
336+/////////////////////////////////////////////////
317337 // $whatsnew: Max number of RecentChanges
318338 $maxshow = 500;
319339
--- a/skin/main.js
+++ b/skin/main.js
@@ -370,8 +370,94 @@ window.addEventListener && window.addEventListener('DOMContentLoaded', function(
370370 }
371371 });
372372 }
373+ function convertExternalLinkToCushionPageLink() {
374+ function domainQuote(domain) {
375+ return domain.replace(/\./g, '\\.');
376+ }
377+ function domainsToRegex(domains) {
378+ var regexList = [];
379+ domains.forEach(function(domain) {
380+ if (domain.substr(0, 2) === '*.') {
381+ // Wildcard domain
382+ var apex = domain.substr(2);
383+ var r = new RegExp('((^.*\\.)|^)' + domainQuote(apex) + '$', 'i');
384+ regexList.push(r);
385+ } else {
386+ // Normal domain
387+ regexList.push(new RegExp('^' + domainQuote(domain) + '$', 'i'));
388+ }
389+ });
390+ return regexList;
391+ }
392+ function domainMatch(domain, regexList) {
393+ for (var i = 0, n = regexList.length; i < n; i++) {
394+ if (regexList[i].test(domain)) {
395+ return true;
396+ }
397+ }
398+ return false;
399+ }
400+ if (!(document.querySelector && JSON)) return;
401+ var location = document.location;
402+ if (location.protocol !== 'http:' && location.protocol !== 'https:') return;
403+ var extLinkInfo = null;
404+ var refInternalDomains = null;
405+ var silentExternalDomains = null;
406+ var extLinkDef = document.querySelector('#pukiwiki-site-properties .external-link-cushion');
407+ if (extLinkDef && extLinkDef.value) {
408+ extLinkInfo = JSON.parse(extLinkDef.value);
409+ refInternalDomains = extLinkInfo.internal_domains;
410+ silentExternalDomains = extLinkInfo.silent_external_domains;
411+ }
412+ if (!Array.isArray(refInternalDomains)) {
413+ refInternalDomains = [];
414+ }
415+ var internalDomains = refInternalDomains.slice();
416+ var hostname = document.location.hostname;
417+ if (internalDomains.indexOf(hostname) < 0) {
418+ internalDomains.push(hostname);
419+ }
420+ if (!Array.isArray(silentExternalDomains)) {
421+ silentExternalDomains = [];
422+ }
423+ var propsE = document.querySelector('#pukiwiki-site-properties .site-props');
424+ if (!propsE) return;
425+ var siteProps = JSON.parse(propsE.value);
426+ var sitePathname = siteProps && siteProps.base_uri_pathname;
427+ if (!sitePathname) return;
428+ var internalDomainsR = domainsToRegex(internalDomains);
429+ var silentExternalDomainsR = domainsToRegex(silentExternalDomains);
430+ var links = document.querySelectorAll('a:not(.external-link):not(.internal-link)');
431+ var classListEnabled = null;
432+ forEach(links, function(link) {
433+ if (classListEnabled === null) {
434+ classListEnabled = link.classList && link.classList.add && true;
435+ }
436+ if (!classListEnabled) return;
437+ var href = link.getAttribute('href');
438+ var m = href.match(/^https?:\/\/([0-9a-zA-Z.-]+)(:\d+)?/);
439+ if (m) {
440+ var host = m[1];
441+ if (domainMatch(host, internalDomainsR)) {
442+ link.classList.add('internal-link');
443+ } else {
444+ if (domainMatch(host, silentExternalDomainsR) ||
445+ link.innerText.replace(/\s+/g, '') === '') {
446+ // Don't show extenal link icons on these domains
447+ link.classList.add('external-link-silent');
448+ }
449+ link.classList.add('external-link');
450+ link.setAttribute('title', href);
451+ link.setAttribute('href', sitePathname + '?cmd=external_link&url=' + encodeURIComponent(href));
452+ }
453+ } else {
454+ link.classList.add('internal-link');
455+ }
456+ });
457+ }
373458 setYourName();
374459 autoTicketLink();
375460 confirmEditFormLeaving();
376461 showPagePassage();
462+ convertExternalLinkToCushionPageLink();
377463 });
--- a/skin/pukiwiki.css
+++ b/skin/pukiwiki.css
@@ -47,6 +47,11 @@ a:hover {
4747 text-decoration:underline;
4848 }
4949
50+a.external-link:not(.external-link-silent)::after {
51+ content:url(../image/external-link.png);
52+ margin:3px;
53+}
54+
5055 h1, h2 {
5156 font-family:verdana, arial, helvetica, Sans-Serif;
5257 color:inherit;
--- a/skin/tdiary.css
+++ b/skin/tdiary.css
@@ -30,6 +30,11 @@ img { border: 0 }
3030 /* --------------------- */
3131 /* PukiWiki original CSS */
3232
33+a.external-link:not(.external-link-silent)::after {
34+ content:url(../image/external-link.png);
35+ margin:3px;
36+}
37+
3338 pre {
3439 white-space:pre-wrap;
3540 word-wrap:break-word;