User:Js/urldecoder.js
Appearance
< User:Js
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
![]() | This user script seems to have a documentation page at User:Js/urldecoder. |
//[[user:js/urldecoder]]
function urlDecoderButton(){
var tlb = document.getElementById('toolbar')
if (!tlb) return
var bt = document.createElement('input')
bt.type = 'button'; bt.onclick = urlDecoderRun
bt.value = '→[\[]]'; bt.id = 'urlDecoder'
bt.title = 'Decode URL before cursor or all URLs in selected text'
bt.style.cssText = 'background:#adbede; height:22px; vertical-align:top; padding:0'
tlb.appendChild(bt)
if (!window.urlDecoderKey) return
bt.accessKey = urlDecoderKey
bt.title += ' ['+urlDecoderKey+']'
updateTooltipAccessKeys([bt])
}
if (wgAction=='edit' || wgAction=='submit') addOnloadHook(urlDecoderButton)
function urlDecoderRun(){ //main function
var httpRegExp = '(https?:\\/\\/[^\\]\\[\\n\\r<>" ]+)' // except []<>"
var beforeCursor = new RegExp('(\\[{0,2})'+httpRegExp+'( +[^\\]\n]+)?\\]{0,2}$', 'i')
var localPrefix = getPrefixes(wgServer.substring(7))
if (wgServer == 'https://secure.wikimedia.org')
localPrefix = getPrefixes(wgScript.split('/')[2]+'.'+wgScript.split('/')[1]+'.org')
var newText, linkSize, txtarea = document.editform.wpTextbox1
var isBeforeCursor = false
if (document.selection) { //IE/Opera
var scrollTop = document.documentElement.scrollTop
txtarea.focus()
range = document.selection.createRange()
if (!range.moveStart) return
if (range.text){
newText = processSelText(range.text)
}else { //no selection
if (!(rr=range.duplicate())) return
rr.moveStart('character', - 1000)
linkSize = processBeforeCursor(rr.text)
if (!linkSize) return
range.moveStart('character', - linkSize) //select matched
}
//replace text
if (newText != range.text){
range.text = newText
if (navigator.userAgent.indexOf('MSIE') != -1) newText = newText.replace(/\r/g,'') //for IE: do not count \r
range.moveStart('character', - newText.length)
range.select()
}
document.documentElement.scrollTop = scrollTop //restore window scroll position
}else if (txtarea.selectionStart || txtarea.selectionStart == '0') { // Mozilla
var scrollTop = txtarea.scrollTop, txt = txtarea.value
txtarea.focus()
var startPos = txtarea.selectionStart, endPos = txtarea.selectionEnd
if (startPos != endPos){
newText = processSelText(txt.substring(startPos, endPos))
}else{ //no selection
linkSize = processBeforeCursor(txt.substring((endPos-1000>0?endPos-1000:0), endPos))
if (!linkSize) return
startPos = endPos - linkSize //select matched
}
//replace text
if (newText != txt.substring(startPos, endPos)){
txtarea.value = txt.substring(0, startPos) + newText + txt.substring(endPos, txtarea.value.length)
txtarea.selectionEnd = startPos + newText.length
txtarea.selectionStart = startPos
}
txtarea.scrollTop = scrollTop
}//end of main function
function processBeforeCursor(str){ //looks for http: inside string, returns it's distance to cursor, also sets newText var
isBeforeCursor = true
var pos = str.lastIndexOf('http://') //to cut out possible preceding http links
if (pos == -1) pos = str.lastIndexOf('https://')
if (pos == -1) return 0
else if (pos > 10) str = str.substring(pos-2) //cut chars before http, leaving some room for possible [
var ma = str.match(beforeCursor) // result: (whole string)' '[', 'http:...', ' name]'
if (!ma) return 0
if (ma[3]) //link with name: add brackets just in case
newText = decodeMatchedLink(ma[0], '[', ma[2], ma[3]+']')
else //just url: add closing bracket if there is leading bracket
newText = decodeMatchedLink(ma[0], ma[1], ma[2], ma[1]?']':'')
return ma[0].length
}
function processSelText(txt){
txt = txt.replace(RegExp('(\\[{0,2})' + httpRegExp + '([^\\]\\[\\n\\r]*?\\]\\]?)?', 'ig'),
decodeMatchedLink)
if (window.urlDecoderIntLinks) txt = txt.replace(/\[\[[^\]\|\n]+/g, decodeWikiLink)
return txt
}
function decodeMatchedLink(str, bracket, url, rest){//gets: (whole string), '[', url, ' name]'
if (!bracket) return decodeLink(url) + str.substring(url.length) //just url
if (!rest) return str //no matching closing bracket
var name = rest.replace(/^ +|\]+$/g,'') //trim leading spaces and ending brackets
str = decodeLink(url, name)
if (str.charAt(0) != '[' ) str = '['+str+']' //not wikilink - restore single brackets
return str
}
function decodeLink(url, name){ //name is optional
var parts, endingDots, result
if (name) name = name.replace(/^ +| +$/g,'') //trim spaces
//secure Wikimedia link into non-secure
url = url.replace(/https:\/\/secure.wikimedia.org\/(\w+)\/(\w+)\/([^\]\|\n\r ]+)/, 'http://$2.$1.org/$3')
//bugzilla
if (parts = url.match(/^https:\/\/bugzilla\.wikimedia.org\/show_bug\.cgi\?id=(\d+)/))
return '[\[mediazilla:'+parts[1]+ (name?'|'+name:'') + ']]'
//decode %
if (url.indexOf('%') != -1) try { url = decodeURI(url) } catch(e){}
url = url.replace(/%(3B|2F|2C|3A)/g, function(s){return decodeURIComponent(s)}) // ;/,:
//encode back some chars not allowed by MediaWiki
url = url.replace(/[ <>"\[\]]/g, function(s){return encodeURIComponent(s)}) //"
if (isBeforeCursor)
for (var n in window.urlDecoderEngNames) //to eng keywords
url = url.replace(RegExp('(title=|wiki\/)('+urlDecoderEngNames[n]+':)'), '$1' + n + ':')
//analyze
parts = url.substring(7).split('/')
var domain = parts[0]
var linkPrefix = getPrefixes(domain)
//return unchanged if cannot convert into wiki link
if (!linkPrefix || parts[1] != 'wiki' || url.indexOf('?')!=-1)
return name ? '[' + url + ' ' + name + ']' : url
//convert to wiki link
var title = url.substring(parts[0].length + parts[1].length + 9) //get part after /wiki/
title = decodeWikiLink(title)
var prefixes = ''
if (linkPrefix[0] && (linkPrefix[0] != localPrefix[0])) prefixes += linkPrefix[0]
if (linkPrefix[1] && (linkPrefix[1] != localPrefix[1])) prefixes += ':'+linkPrefix[1]
if (prefixes) prefixes += ':'
if (!prefixes && isColonNeeded(title)) prefixes = ':' //leading colon for cat/file
//return result
result = '[\[' + prefixes + title
if (name) result += '|' + name + ']]'
else result = (result + ']]').replace(/(\.+)\]\]/,']]$1') //url. -> [[w]]. not [[w.]]
return result
}
function decodeWikiLink(link){
link = link.replace(/_/g, ' ').replace(/^ +| +$/g, '')
var parts = link.split('#')
if (parts.length != 2) return link
var anchor = parts[1], hidIdx = -1, hidden = []
link = parts[0]
anchor = anchor.replace( //hide IPs
/(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/,
function(s){ hidden[++hidIdx] = s; return '\x01' + hidIdx + '\x02' }
)
//decode 4, 3 and 2-byte: http://en.wikipedia.org/wiki/UTF-8
anchor = anchor.replace(/\.F[0-4]\.[89AB][\dA-F]\.[89AB][\dA-F]\.[89AB][\dA-F]/g, deChar)
anchor = anchor.replace(/\.E[\dA-F]\.[89AB][\dA-F]\.[89AB][\dA-F]/g, deChar)
anchor = anchor.replace(/\.[CD][\dA-F]\.[89AB][\dA-F]/g, deChar)
//decode reserved 1-byte chars: http://meta.wikimedia.org/wiki/Url , http://en.wikipedia.org/wiki/Percent_encoding
anchor = anchor.replace(/\.[2-5][0-9A-F]/g, function(str){
var ch = deChar(str) // ;:@&=+$,/?%#[]<>
if ((ch != ':') &&
((encodeURIComponent(ch).replace(/%/,'.') == str) || ('!*\'()'.indexOf(ch) != -1)))
return ch
else
return str //do not decode e.g. %35 which is '5' and not supposed to be encoded
})
function deChar(str){ return tryDecode(str.replace(/\.([0-9A-F][0-9A-F])/g, '%$1')) }
function tryDecode(s){ try {s = decodeURIComponent(s)} catch(e){}; return s }
//unhide IPs
for (var i=hidIdx; i>=0; i--) anchor = anchor.replace('\x01'+i+'\x02', hidden[i])
//return
return link + '#' + anchor
}
function getPrefixes(domain){ //en.wikipedia.org -> [ 'w', 'en'] , using projPrefix{}
var projPrefix = {
'test.wikipedia.org':'testwiki',
'wikipedia.org':'w',
'wikibooks.org':'b',
'wikinews.org':'n',
'wikiquote.org':'q',
'wikisource.org':'s',
'wikiversity.org':'v',
'wiktionary.org':'wikt',
'mediawiki.org':'mw',
'www.wikimedia.org':'foundation',
'wikimedia.org':'*',
'wikimediafoundation.org':'foundation'
}
domain = domain.toLowerCase()
var proj, isFound
for (proj in projPrefix) if (domain.indexOf(proj) != -1) {isFound=true; break}
if (!isFound) return null
var prefix = projPrefix[proj], lang = ''
if (prefix == '*') prefix = domain.split('.')[0] // .wikimedia.org project
else if ((domain=domain.replace(proj, '')) && (domain != 'www.')) lang = domain.split('.')[0] //multi-lang project
//else if (prefix.charAt(0) == ':'){ //multi-lang project if (pp.length == 3) lang = pp[0]
return [prefix, lang]
}
function isColonNeeded(pg){
if (pg.indexOf(':')==-1) return false
urlDecoderNS = window.urlDecoderNS || {}
urlDecoderNS.en = 'image'
var ns = urlDecoderNS[wgContentLanguage]
if (typeof ns != 'string') ns = requestColonNS()
return RegExp('^('+ns+'|file|category) *:','i').test(pg)
}
function requestColonNS(){
var whatsthis = ' <a href="http://en.wikipedia.org/wiki/user:js/urldecoder#Localization" target=_blank>(?)</a>'
showMsg('Requesting namespaces...'+whatsthis)
var aj = sajax_init_object(), q = null, ns = []
aj.open('GET', '/w/api.php?format=json&action=query&meta=siteinfo&siprop=namespaces|namespacealiases', false)
aj.send(null)
try { eval('q='+aj.responseText); q = q.query
} catch(e){return null}
ns.push(q.namespaces[6]['*']); ns.push(q.namespaces[14]['*'])
for (var k in q.namespacealiases)
if (q.namespacealiases[k].id==6 || q.namespacealiases[k].id==14)
ns.push(q.namespacealiases[k]['*'])
ns = ns.join('|').toLowerCase()
urlDecoderNS[wgContentLanguage] = ns
showMsg("<code>urlDecoderNS = {'"+wgContentLanguage+"':'"+ns+"'}<code>"+whatsthis)
return ns
}
function showMsg(htm){
var dv = document.getElementById('edit-msg')
if (!dv){
dv = document.createElement('div')
dv.id = 'edit-msg'; dv.style.cssText = 'margin:5px; border:1px solid gray'
var tbox = document.getElementById('wpTextbox1')
tbox.parentNode.insertBefore(dv, tbox)
}
dv.innerHTML = htm; dv.style.display = ''
setTimeout(hideMsg, 15000)
}
function hideMsg(){
var dv = document.getElementById('edit-msg')
dv.style.display = 'none'
}
}