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 解決了該問題。連結:
好的,接下來該上操作步驟了。首先,新建了資料夾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方法,該方法的功能,是為了將超連結指向新的視窗。
總的就是這樣。