1. 程式人生 > >USTCOJ程式碼檢視功能的實現(我的第一個Chrome外掛,UstcOjSourceView)

USTCOJ程式碼檢視功能的實現(我的第一個Chrome外掛,UstcOjSourceView)

因工作需要,會不時的在USTCOJ上產看程式原始碼。檢視原始碼的流程通常是這樣的:

1,根據指定題號、賬號,或許相關的RunID。

3,在如下所示的輸入框中輸入RunID號,點選View按鈕檢視程式碼。


(圖片一)

採用這種方式檢視原始碼是相當痛苦的,因為judge.php是通過POST方式傳遞RunID值的,也就是說,每次檢視原始碼的時候,都需要返回上述頁面,然後輸入ID號,再點選View按鈕檢視程式碼。


(圖片二)

現在,我想要做的工作又兩個:

1,編寫一個php指令碼,實現檢視原始碼的功能,而且該php檔案通過GET方式來獲取RunID引數,從而可以方便的通過URL訪問到原始碼。當然,該PHP指令碼還應該具備訪問許可權控制。

2,編寫一個Chrome外掛,將圖片二中所示的RunID一列的文字更改為指向類似http://acm.ustc.edu.cn/admin1/viewsource.php?id=78651的超文字。之所以不在伺服器端修改對應的php指令碼(如status.php)。是因為對於一般使用者而言,該RunID就只應該是一個純文字欄位。採用外掛的形式,既能保證需要用到它的人看到超連結,又能保證不破壞原有程式碼。

工作一:編寫viewsource.php指令碼,該指令碼程式碼結構如下:


該指令碼的第4行判斷使用者是否已經登入,若未登入(及對應的SESSION欄位為空),則顯示登入框。第10~14行則表示在使用者登入的情況下,通過GET獲取id的值。並將程式碼展示出來。

指令碼17~21行則執行登入操作。後面的23~134是對應的三個函式的定義。由於login及showSource函式中需要查詢資料庫,其中admin.php指令碼包含了資料庫的連線等初始化操作。

工作二:編寫Chrome外掛

主要參考了以下兩個連結:

此外,還參考了“中科大圖書館豆瓣外掛”。在此感謝相關作者。

編寫完外掛進行除錯的時候,還遇到了Could not load extension from . The ‘manifest_version’ key must be present and set to 2錯誤。搜尋到一些連結,通過新增“manifest_version”: 2 解決了該問題。連結:

http://www.viphper.com/?p=423

好的,接下來該上操作步驟了。首先,新建了資料夾UstcOjSourceView。並準備了一個128×128的icon圖示。程式碼如下圖所示:


其中manifest.json檔案內容如下:

{
    "name" : "UstcOjSourceView",
    "version" : "1.0",
	"manifest_version" : 2,
    "description" : "將UstcOj頁面表格中的Runid更改為超文字連結",
    "content_scripts" : [
        {
            "js" : ["Runidlinked.js"],
            "matches" : ["http://acm.ustc.edu.cn/ustcoj/*"
            ],
            "run_at" : "document_end"
        }
    ]
}

該json檔案中content_scripts的含義如下:當訪問以http://acm.ustc.edu.cn/ustcoj/開頭的URL的時候,在文件載入結束之後,執行Runidlinked.js檔案。

其中Runidlinked.js程式碼如下:
String.prototype.blanklink = function(str)
{
	url = this.link(str);
	offset = url.indexOf('">');
	url = url.substring(0, offset) + '" target="_blank">' + url.substring(offset+2);		
	return url;
}

document.getElementsByClassName = function(className)
{
	var elem = this.getElementsByTagName('td');
	var result = [];
	for (i in elem) 
	{
		if (className == elem[i].className)
			result.push(elem[i]);
	}
	return result;
};

function getURL(text)
{
	url = "http://acm.ustc.edu.cn/admin1/viewsource.php?id=";
	url += text;
	return text.blanklink(url);
}

function change()
{
	var divs = document.getElementsByClassName('table_runid');
	for(i in divs)
	{
		text = divs[i].innerText;
		divs[i].innerHTML = getURL(text);
	}
}

change();
特別需要留意的,是最後一行程式碼change();因為在它之前都只是函式定義,而只有這一行程式碼,才是整個功能實現的關鍵。

上述JS指令碼總體而言還是比較簡單的,其中getElementsByClassName是為了獲取頁面中的<td class="table_runid">,因為這些節點,就是呈現RunID內容的HTML。而其中blanklink,則是為字串物件新增一個blanklink方法,該方法的功能,是為了將超連結指向新的視窗。

總的就是這樣。