사용자:Hsl0/연구소/2.js: 두 판 사이의 차이

리버티게임, 모두가 만들어가는 자유로운 게임
imported>Hsl0
(새 문서: var punycode = require('ext.gadget.punycode'); function requestMetadata() { var queue = metadataQueue; $.get('/w/api.php', { action: "query", format: "json", prop: "revisions...)
 
imported>Hsl0
편집 요약 없음
 
(같은 사용자의 중간 판 33개는 보이지 않습니다)
1번째 줄: 1번째 줄:
var punycode = require('ext.gadget.punycode');
/**
 
* [[틀:CGI보호]]
function requestMetadata() {
* CGI나 주소를 조작하지 못하게 합니다.
var queue = metadataQueue;
* 제작자: [[사용자:hsl0|hsl0]]
$.get('/w/api.php', {
**/
action: "query",
(function protectCGI() {
format: "json",
function getTitle(pagename) {
prop: "revisions",
pagename = pagename.split('/')[0].split(':');
titles: Object.keys(queue).join('|'),
var ns = pagename[0].replace(/talk|토론/gi, '');
formatversion: 2,
return ns + (ns && ':') + pagename[1];
rvprop: "content",
}
rvslots: "main"
}).then(function(res) {
function compareObject(a, b) {
res.query.pages.forEach(function(obj) {
var aKey = Object.keys(a);
queue[obj.title](JSON.parse(obj.revisions[0].slots.main.content));
var bKey = Object.keys(b);
});
});
metadataQueue = {};
metaRqTimeout = null;
}
function newPage(name, label, prefix) {
function create(res) {
var $table = keyList(keys, res.about, res.loc);
var reload = new OO.ui.ButtonInputWidget({
if(aKey.length !== bKey.length) return false;
label: '새로고침',
icon: 'reload'
});
reload.$button.click(function() {
reload.setDisabled(true);
reload.setFlags('pending');
Promise.all([hybridStorage.refresh(), loadAbout()]).then(function(res) {
allkeys = getKeys();
keys = name === 'global'? allkeys.global : allkeys.local[prefix];
page.$element.find('table').remove();
$table = keyList(keys, res[1].about, res[1].loc);
page.$element.append($table);
reload.setDisabled(false);
reload.setFlags({pending: false});
}, notifyApiError.bind(null, '항목을 불러오는 데 실패했습니다.', null));
});
var remove = new OO.ui.ButtonInputWidget({
classes: ['removeall'],
label: '모두 제거',
icon: 'trash',
flags: 'destructive'
});
remove.$button.click(function() {
OO.ui.confirm('정말로 ' + (name === 'global'? '모든 전역키' : '"' + label + '"의 모든 키') + '를 제거하시겠습니까?').then(function(response) {
var process;
if(response) {
remove.setDisabled(true);
remove.setFlags('pending');
for(var key in keys) process = hybridStorage.removeItem(keys[key]);
process.then(function() {
if(name === 'global') {
keys = allkeys.global = {};
page.$element.find('table').remove();
$table = keyList(keys);
page.$element.append($table);
} else {
delete allkeys.local[prefix];
layout.removePages([page]);
}
remove.setDisabled(false);
remove.setFlags({pending: false});
}, notifyApiError.bind(null, '항목을 제거하지 못했습니다.', null));
}
});
});
var revert = new OO.ui.ButtonInputWidget({
classes: ['revertall'],
label: '모두 복원',
icon: 'undo',
flags: 'progressive'
});
revert.$button.click(function() {
$table.find('.removed .revert button').click();
});
for(var key in a) {
if(a[key] !== b[key]) return false;
}
page.$element.empty().append([
return true;
$('<h2 />').html(name === 'global'? '전역키' : $('<a />', {href: mw.util.getUrl(label), target: '_blank'}).text(label)),
$('<div />', {
class: 'buttons'
}).append(new OO.ui.ButtonGroupWidget({
items: [reload],
classes: ['buttons-left']
}).$element).append(new OO.ui.ButtonGroupWidget({
items: [revert, remove],
classes: ['buttons-right']
}).$element),
$table
]);
}
function loadAbout() {
if(name === 'global') return $.get('/w/index.php?title=틀:DB2/전역키&action=render').then(function(res) {
function process(key) {
var $row = $(res).find('tr:has(td:nth-child(1):contains(' + JSON.stringify(key) +'))');
about[key] = $row.find('td')[1].innerText;
loc[key] = $row.find('td:nth-child(4)');
loc[key].find(':not(a)').contents().unwrap();
loc[key].find('a').filter(function() {
var href = new URL(this.href, location);
href.search = '';
this.href = href;
this.target = '_blank';
return href.origin !== location.origin || !href.pathname.startsWith('/w');
}).contents().unwrap();
loc[key] = loc[key].html();
}
var about = {};
var loc = {};
if(DEFAULT_KEY in keys) process(DEFAULT_KEY);
for(var key in keys) process(key);
return {
about: about,
loc: loc
};
});
else return new Promise(function(resolve) {
if(metaRqTimeout) clearTimeout(metaRqTimeout);
metadataQueue[prefix + '/game.json'] = function(res) {
var about = {};
if(res.gameDB.default) about[DEFAULT_KEY] = res.gameDB.default.description;
if(res.gameDB.keys) for(var key in res.gameDB.keys) {
about[key] = res.gameDB.keys[key].description;
}
resolve({about: about});
};
metaRqTimeout = setTimeout(requestMetadata, 100);
});
}
}
loadAbout().then(create);
var keys = name === 'global'? allkeys.global : allkeys.local[prefix];
function filterLink() {
var href = new URL(this.href, location);
var page = new OO.ui.PageLayout(name, {
var params = geturlSearch(href);
content: [new OO.ui.ProgressBarWidget()]
});
page.setupOutlineItem = function() {
this.outlineItem.setLabel(label);
};
return page;
}
function encode(key) {
return encodeURIComponent(punycode.toASCII(key))
.replace(/\./g, '%2E')
.replace(/!/g, '%21')
.replace(/~/g, '%7E')
.replace(/\*/g, '%2A')
.replace(/'/g, '%27')
.replace(/\(/g, '%28')
.replace(/\)/g, '%29')
.replace(/_/g, '__')
.replace(/%/g, '_');
}
function decode(key) {
return punycode.toUnicode(decodeURIComponent(key.replace(/_(?=[a-zA-Z0-9]{2})/g, '%').replace(/__/g, '_')));
}
function keyList(keys, abouts, locs) {
function keyRow(key) {
var origin = keys[key];
var val = hybridStorage.getItem(origin);
var about = abouts && abouts[key];
var loc = locs && locs[key];
if(val === null) return;
var copy = new OO.ui.ButtonWidget({
classes: ['copy'],
label: '복사'
});
copy.$button.click(function() {
navigator.clipboard.writeText(val);
});
var remove = new OO.ui.ButtonInputWidget({
classes: ['remove'],
label: '제거',
flags: 'destructive'
});
remove.$button.click(function() {
remove.setDisabled(true);
remove.setFlags('pending');
hybridStorage.removeItem(origin).then(function() {
$element.addClass('removed');
$options.data('sort-value', 0);
remove.$element.addClass('hidden');
revert.$element.removeClass('hidden');
revert.setDisabled(false);
remove.setFlags({pending: false});
}, notifyApiError.bind(null, '항목을 제거하지 못했습니다.', null));
});
var revert = new OO.ui.ButtonInputWidget({
classes: ['revert', 'hidden'],
label: '복원',
flags: 'progressive',
disabled: true
});
revert.$button.click(function() {
revert.setDisabled(true);
revert.setFlags('pending');
hybridStorage.setItem(origin, val).then(function() {
keys[key] = origin;
$element.removeClass('removed');
revert.$element.addClass('hidden');
remove.$element.removeClass('hidden');
remove.setDisabled(false);
revert.setFlags({pending: false});
}, notifyApiError.bind(null, '항목을 복원하지 못했습니다.', null));
});
var $options = $('<td />', {'data-sort-value': 1}).append(copy.$element).append(remove.$element).append(revert.$element);
if(href.host !== location.host) return false;
if(params.action || params.oldid) return false;
if(href.pathname.startsWith('/wiki/')) params.title = href.pathname.slice(6);
if(getTitle(params.title) !== title) return false;
var $element = $('<tr />', {id: 'key-' + origin})
$(this).data('params', params);
.append($('<td />').append(key === DEFAULT_KEY? $('<span />', {class: 'key key-default'}).text('기본키') : $('<span />', {class: 'key'}).text(key)))
.append($('<td />', {class: 'about'}).text(about))
.append($('<td />').html($('<pre />', {class: 'content'}).text(val)))
.append(loc && $('<td />', {class: 'location'}).html(loc))
.append($options);
return $element;
return true;
}
}
var rows = [];
var params = geturlSearch();
params.title = mw.config.get('wgPageName');
var title = getTitle(params.title);
var protect = document.getElementById('protectCGI');
var cheat = null;
var temp = localStorage.getItem('protectCGI-temp');
var data = sessionStorage.getItem('protectCGI');
var link;
if(DEFAULT_KEY in keys) rows.push(keyRow(DEFAULT_KEY));
registerRenderer(function() {
$('.protectCGI-link-container a').filter(filterLink).addClass('protectCGI-link');
for(var key in keys) rows.push(keyRow(key));
$('.protectCGI-link-container a:not(.protectCGI-link)').addClass('protectCGI-link-no');
});
if(!rows.length) rows.push($('<tr />').append($('<td />', {
colspan: locs? 4 : 5,
class: 'key-empty'
}).text('(키 없음)')));
return $('<table class="wikitable sortable" width="100%" />')
.append('<thead><tr><th>키</th><th>설명</th><th>값</th>' + (locs && '<th>사용처</th>') + '<th>옵션</th></tr></thead>')
.append($('<tbody />').append(rows)).tablesorter();
}
var fromKey, toKey;
if(mw.user.isAnon()) {
fromKey = function(key) {
return key.slice(7);
};
toKey = function(key) {
return 'gamedb-' + key;
};
} else {
fromKey = function(key) {
return decode(key.slice(7));
};
toKey = function(key) {
return 'gamedb-' + encode(key);
};
}


var layout = new OO.ui.BookletLayout({
registerHandler(function() {
outlined: true
function hijack(link) {
});
var title;
if(link.href && link.href != location.href) location.replace(link.href);
else if(data) {
data = JSON.parse(data);
title = data.title;
delete data.title;
location.replace(mw.util.getUrl(title, data));
} else if(document.referrer) history.back();
else location.replace(mw.util.getUrl(getTitle(mw.config.get('wgPageName'))));
}
if(protect) (function() {
var clicked;
link = $(protect).find('a').click(function(event) {
event.preventDefault();
if(this === clicked) {
if('wait' in this.dataset) {
if(this.dataset.wait <= 0) {
event.stopImmediatePropagation();
hijack(this);
}
} else hijack(this);
} else {
clicked = this;
this.click();
}
});


var DEFAULT_KEY = Symbol('defaultkey');
if(params.action || params.oldid) return;
 
else cheat = false;
var allkey, scopes;
 
if(data) {
function getKeys() {
data = JSON.parse(data);
allkey = Object.getOwnPropertyNames(hybridStorage).filter(function(key) {
cheat = !compareObject(data, params);
return key.startsWith('gamedb-');
} else cheat = true;
}).map(fromKey);
})();
else if(!(params.action || params.oldid)) cheat = false;
var keys = {global:{}, local:{}};
scopes = new Set();
allkey.forEach(function(key) {
key = key.split('/')[0];
if(!key.startsWith('#') && key.includes(':')) scopes.add(key);
});
// global
allkey.filter(function(key) {
return key.startsWith('#');
}).forEach(function(key) {
keys.global[key.slice(1)] = toKey(key);
});
// local
scopes.forEach(function(scope) {
var current = {};
allkey.filter(function(key) {
if(cheat === false) $('.protectCGI-link').click(function(event) {
return key.startsWith(scope);
sessionStorage.setItem('protectCGI', JSON.stringify($(this).data('params')));
}).forEach(function(key) {
if(protect) {
key = key.length < scope.length + 1? DEFAULT_KEY : key.slice(scope.length + 1);
event.preventDefault();
current[key] = toKey(key === DEFAULT_KEY? scope : scope + '/' + key);
location.replace(this.href);
}
});
});
keys.local[scope] = current;
window.addEventListener('hashchange', function(event) {
var data, dataObj;
if(location.hash.endsWith('##emergency-save')) {
data = sessionStorage.getItem('protectCGI');
if(data) dataObj = JSON.parse(data);
if(data && dataObj.title === params.title) localStorage.setItem('protectCGI-temp', data);
}
});
});
});
return keys;
registerTrigger(function() {
}
if(temp) {
 
if(!data) {
var allkeys = getKeys();
sessionStorage.setItem('protectCGI', temp);
 
data = temp;
layout.addPages([newPage('global', '전역키')]);
mw.loader.using('oojs-ui-windows').then(function() {
 
OO.ui.confirm('비상 저장된 세션이 있습니다. 다시 돌아가겠습니까?').then(function(res) {
layout.addPages(Array.from(scopes).map(function(prefix) {
var data = JSON.parse(temp);
return newPage('local-' + prefix, prefix, prefix);
var title;
}));
if(res && !compareObject(params, data)) {
 
title = data.title;
function handleReset(wrong) {
delete data.title;
var rand = Math.floor(Math.random() * 999);
location.href = mw.util.getUrl(data.title, data);
rand = '0'.repeat(3 - rand.toString().length) + rand;
}
});
OO.ui.prompt($('<p>' + (wrong? '잘못 입력하였습니다.' : 'DB2의 모든 데이터가 초기화됩니다.') + ' 계속하시려면 <b>' + rand + '</b>를 입력해 주세요.</p>'), {
});
textInput: {
}
validate: new RegExp(rand)
localStorage.removeItem('protectCGI-temp');
}
}
}).then(function(res) {
if(res === rand) layout.$element.find('.removeall').click();
else if(res !== null) handleReset(true);
})
}
$(function() {
try {
var metadataQueue = {};
var metaRqTimeout = null;
var reset = new OO.ui.ButtonInputWidget({
if(cheat) {
id: 'reset',
if(link.length) link.click();
label: '전체 초기화',
else if(data) {
icon: 'trash',
title = data.title;
flags: 'destructive'
delete data.title;
});
location.replace(mw.util.getUrl(title, data));
reset.$button.click(handleReset.bind(null, false));
}
else if(document.referrer) history.back();
else location.replace(mw.util.getUrl(getTitle(mw.config.get('wgPageName'))));
}
$('#mw-content-text').html(new OO.ui.PanelLayout({
if(cheat === false) {
expanded: false,
document.body.classList.add('protectCGI-done');
framed: true,
$('.protectCGI-only').show();
content: [layout]
}
}).$element).prepend($('<div />', {id: 'globalbuttons'}).append(reset.$element));
});
} catch(err) {
})();
$('#mw-content-text').html($('<span />', {
class: 'error'
}).text(err));
}
});

2021년 1월 13일 (수) 00:56 기준 최신판

/**
 * [[틀:CGI보호]]
 * CGI나 주소를 조작하지 못하게 합니다.
 * 제작자: [[사용자:hsl0|hsl0]]
**/
(function protectCGI() {
	function getTitle(pagename) {
		pagename = pagename.split('/')[0].split(':');
		var ns = pagename[0].replace(/talk|토론/gi, '');
		return ns + (ns && ':') + pagename[1];
	}
	
	function compareObject(a, b) {
		var aKey = Object.keys(a);
		var bKey = Object.keys(b);
		
		if(aKey.length !== bKey.length) return false;
		
		for(var key in a) {
			if(a[key] !== b[key]) return false;
		}
		
		return true;
	}
	
	function filterLink() {
		var href = new URL(this.href, location);
		var params = geturlSearch(href);
		
		if(href.host !== location.host) return false;
		if(params.action || params.oldid) return false;
		if(href.pathname.startsWith('/wiki/')) params.title = href.pathname.slice(6);
		if(getTitle(params.title) !== title) return false;
		
		$(this).data('params', params);
		
		return true;
	}
	
	var params = geturlSearch();
	params.title = mw.config.get('wgPageName');
	var title = getTitle(params.title);
	var protect = document.getElementById('protectCGI');
	var cheat = null;
	var temp = localStorage.getItem('protectCGI-temp');
	var data = sessionStorage.getItem('protectCGI');
	var link;
	
	registerRenderer(function() {
		$('.protectCGI-link-container a').filter(filterLink).addClass('protectCGI-link');
		$('.protectCGI-link-container a:not(.protectCGI-link)').addClass('protectCGI-link-no');
	});

	registerHandler(function() {
		function hijack(link) {
			var title;
			
			if(link.href && link.href != location.href) location.replace(link.href);
			else if(data) {
				data = JSON.parse(data);
				title = data.title;
				delete data.title;
				location.replace(mw.util.getUrl(title, data));
			} else if(document.referrer) history.back();
			else location.replace(mw.util.getUrl(getTitle(mw.config.get('wgPageName'))));
		}
		
		if(protect) (function() {
			var clicked;
			link = $(protect).find('a').click(function(event) {
				event.preventDefault();
				if(this === clicked) {
					if('wait' in this.dataset) {
						if(this.dataset.wait <= 0) {
							event.stopImmediatePropagation();
							hijack(this);
						}
					} else hijack(this);
				} else {
					clicked = this;
					this.click();
				}
			});

			if(params.action || params.oldid) return;
			else cheat = false;
			
			if(data) {
				data = JSON.parse(data);
				cheat = !compareObject(data, params);
			} else cheat = true;
		})();
		else if(!(params.action || params.oldid)) cheat = false;
		
		if(cheat === false) $('.protectCGI-link').click(function(event) {
			sessionStorage.setItem('protectCGI', JSON.stringify($(this).data('params')));
			if(protect) {
				event.preventDefault();
				location.replace(this.href);
			}
		});
		
		window.addEventListener('hashchange', function(event) {
			var data, dataObj;
			if(location.hash.endsWith('##emergency-save')) {
				data = sessionStorage.getItem('protectCGI');
				if(data) dataObj = JSON.parse(data);
				if(data && dataObj.title === params.title) localStorage.setItem('protectCGI-temp', data);
			}
		});
	});
	
	registerTrigger(function() {
		if(temp) {
			if(!data) {
				sessionStorage.setItem('protectCGI', temp);
				data = temp;
				mw.loader.using('oojs-ui-windows').then(function() {
					OO.ui.confirm('비상 저장된 세션이 있습니다. 다시 돌아가겠습니까?').then(function(res) {
						var data = JSON.parse(temp);
						var title;
						if(res && !compareObject(params, data)) {
							title = data.title;
							delete data.title;
							location.href = mw.util.getUrl(data.title, data);
						}
					});
				});
			}
			localStorage.removeItem('protectCGI-temp');
		}
		
		if(cheat) {
			if(link.length) link.click();
			else if(data) {
				title = data.title;
				delete data.title;
				location.replace(mw.util.getUrl(title, data));
			}
			else if(document.referrer) history.back();
			else location.replace(mw.util.getUrl(getTitle(mw.config.get('wgPageName'))));
		}
		
		if(cheat === false) {
			document.body.classList.add('protectCGI-done');
			$('.protectCGI-only').show();
		}
	});	
})();