미디어위키:Gadget-PluginX.js: 두 판 사이의 차이

리버티게임(개발), 모두가 만들어가는 자유로운 게임
둘러보기로 이동 검색으로 이동
imported>이의섭
(hsl0님의 요청 수용)
imported>Senouis
(pluginX가 사이트 로딩 성능을 저하하는 구조라 api.getDocument를 비동기 통신 기반 함수로 대체할 때까지 임시로 조치)
6번째 줄: 6번째 줄:


function pluginXCore() {
function pluginXCore() {
    // pluginX를 쓰지 않으면 이 가젯을 사용할 이유 없음, span 태그를 감지하여 pluginX를 문서가 사용하는지 확인
    if (document.getElementsByClassName("c_pluginX").length == 0) return; // NOTE: getDocument 제거 작업이 진행될 때까지 삭제 금지
   
     var api = MediaWikiAPI();
     var api = MediaWikiAPI();
     var ipUser = false;
     var ipUser = false;
29번째 줄: 32번째 줄:
     };
     };
     };
     };
   
     /// 플러그인 목록을 만들어서 script_list[]에 담습니다.
     /// 플러그인 목록을 만들어서 script_list[]에 담습니다.
     var getPluginList = function(){
     var getPluginList = function(){
89번째 줄: 91번째 줄:
     var showWindow = function(){
     var showWindow = function(){
     html_before = document.getElementById('mw-content-text').innerHTML;
     html_before = document.getElementById('mw-content-text').innerHTML;
    // TODO: api.readDocument 대신 mw.Api.get({적절한 문서 데이터 헤더}).then(...)를 사용해서 비동기로 통신하도록 개조
     $('#mw-content-text').html(api.readDocument("틀:PluginX/setup"));
     $('#mw-content-text').html(api.readDocument("틀:PluginX/setup"));
     var script = "";
     var script = "";

2023년 5월 31일 (수) 22:10 판

/**
 * pluginX Core
 * pluginX 시스템이 제대로 돌아가게 해 줍니다.
 * 작성자: [[사용자:Bd3076|Bd3076]]
*/

function pluginXCore() {
    // pluginX를 쓰지 않으면 이 가젯을 사용할 이유 없음, span 태그를 감지하여 pluginX를 문서가 사용하는지 확인
    if (document.getElementsByClassName("c_pluginX").length == 0) return; // NOTE: getDocument 제거 작업이 진행될 때까지 삭제 금지
    
    var api = MediaWikiAPI();
    var ipUser = false;
	
	if(mw.config.get("wgUserName") === null) ipUser = true;
	
    var script_list = [];
    var pluginExist = false;
    var neededPluginExist = false;
    var html_before;
    var jsonDoc = "사용자:" + mw.config.get("wgUserName") + "/pluginX.json";
    var jsonData = JSON.parse(api.getDocument(jsonDoc));
    
    /// 플러그인의 정보가 담긴 데이터를 만듭니다.
    var generateScriptData = function(_url, _name, _creator, _doc, _script, _revid){
    	return {
    		url: _url,
    		name: _name,
    		creator: _creator,
    		doc: _doc,
    		script: _script,
    		revid: _revid
    	};
    };
    /// 플러그인 목록을 만들어서 script_list[]에 담습니다.
    var getPluginList = function(){
    	$(".c_pluginX").each(function() {
    		pluginExist = true;
    		var url = $(this).attr('data-url');
    		var name = $(this).attr('data-name');
    		var creator = $(this).attr('data-creator');
    		var doc = $(this).attr('data-doc');
    		var revid = $(this).attr('data-revid');
    		
    		var script = api.getDocument(doc);
    		
    		script_list.push(generateScriptData(url, name, creator, doc, script, revid));
    		
    		if(jsonData[doc] === undefined || jsonData[doc] !== revid){
    			console.log(name);
    			neededPluginExist = true;
    		}
    	});
    };
    
    /// 플러그인을 실행합니다.
    var executePlugins = function(){
    	if(html_before) document.getElementById('mw-content-text').innerHTML = html_before;
    	script_list.forEach(function(data){
    		var link = data.url;
    		var revid = data.revid;
    		var doc = data.doc;
    		
    		if(neededPluginExist){
    			jsonData[doc] = revid;
    		}
    		
    		$.getScript(link);
    	});
    	
    	///자동 인증된 사용자가 플러그인을 실행할 경우 json을 갱신합니다.
    	var userGroups = mw.config.get('wgUserGroups');
        var autocheck = 0;
        if (userGroups) {
        	for (var i = 0; i < userGroups.length; i++) {
        		if (userGroups[i] === 'autoconfirmed') {
        			autocheck++;
        		}
        	}
        }
    	if(neededPluginExist && !(autocheck === 0) ){
    		api.changeDocument(jsonDoc, "pluginX - 새로운 플러그인", JSON.stringify(jsonData), true, true);
    	}
    };
    
    /// 플러그인을 실행하지 않습니다.
    var doNotExecutePlugins = function(){
    	document.getElementById('mw-content-text').innerHTML = html_before;
    };
    
    /// 알림 창을 만듭니다.
    var showWindow = function(){
    	html_before = document.getElementById('mw-content-text').innerHTML;
    	// TODO: api.readDocument 대신 mw.Api.get({적절한 문서 데이터 헤더}).then(...)를 사용해서 비동기로 통신하도록 개조
    	$('#mw-content-text').html(api.readDocument("틀:PluginX/setup"));
    	var script = "";
    	
    	script_list.forEach(function(data){
    		var addingCode;
    		addingCode = '<div class="px-code"><pre>';
    		addingCode = addingCode.concat(((data.script.replace(/&/g, '&amp;')).replace(/</g, '&lt;')).replace(/>/g, '&gt;'));
    		addingCode = addingCode.concat('</pre> </div> <div class="px-codeinfo"> <ul> <li> 플러그인 이름: ');
    		addingCode = addingCode.concat(data.name);
    		addingCode = addingCode.concat('</li> <li> 플러그인 제작자: ');
    		addingCode = addingCode.concat(data.creator);
    		addingCode = addingCode.concat('</li> </ul> </div>');
    		
    		// 위험 코드 탐지 시작
    		var pattern;
    		var nscode = data.script.replace(/\r?\n|\r/g, ' ');
    		
    		// 패턴 1. document.innerHTML 사용 (위험도: 심각)
    		pattern = new RegExp("^.*document *\. *innerHTML.*$");
    		
    		if(pattern.test(nscode)){
    			addingCode = addingCode.concat('<div class="px-critical">이 플러그인은 문서 열람 시 지장을 줄 수 있습니다.<br>플러그인 제작자를 신뢰할 수 있는 경우에만 실행하시기 바랍니다.</div>');
    		}
    		
    		// 패턴 2. document.write 사용 (위험도: 심각)
    		pattern = new RegExp("^.*document *\. *write.*$");
    		
    		if(pattern.test(nscode)){
    			addingCode = addingCode.concat('<div class="px-critical">이 플러그인은 문서 내용을 왜곡시킬 수 있습니다.<br>플러그인 제작자를 신뢰할 수 있는 경우에만 실행하시기 바랍니다.</div>');
    		}
    		
    		// 패턴 3. "wgUserName" 사용 (위험도: 안내)
    		pattern = new RegExp('^.*"wgUserName".*$');
    		
    		if(pattern.test(nscode)){
    			addingCode = addingCode.concat('<div class="px-notice">이 플러그인은 당신의 사용자 이름을 수집합니다.<br>이를 원치 않으시면 플러그인을 실행하지 마시기 바랍니다.</div>');
    		}
    		
    		//패턴 4. MediaWikiAPI.changeDocument 사용(위험도: 경고)
    		pattern = new RegExp('^.*MediaWikiAPI.*changeDocument.*$');
    		
    		if(pattern.test(nscode)){
    			addingCode = addingCode.concat('<div class="px-warning">이 플러그인은 다른 문서를 편집합니다.<br>이 게임이 계정 생성형 게임일 가능성이 높습니다.<br>플러그인 제작자를 신뢰할 수 있는 경우에만 실행하시기 바랍니다.</div>');
    		}
    		
    		script += addingCode;
    	});
    	
    	document.getElementById('px-script').innerHTML = script;
    
		$('#px-button').on('click', executePlugins);
		$('#px-button2').on('click', doNotExecutePlugins);
    };
    
    getPluginList();
    
    if(pluginExist === false) return;
    
    if(neededPluginExist === false){
    	executePlugins();
    	return;
    }
    else{
	    showWindow();
	    return;
    }
}
$(pluginXCore);

/* pluginX Core 끝 */