add option to disable mixed content security, workaround for ajax restrictions
This commit is contained in:
parent
e70cdc620a
commit
790a62d1bd
@ -54,8 +54,8 @@ Redirect =
|
||||
# For fuuka-based archives:
|
||||
# https://github.com/eksopl/fuuka/issues/27
|
||||
protocol = Redirect.protocol archive
|
||||
return '' unless protocol is 'https://' or location.protocol is 'http:'
|
||||
URL = new String "#{protocol}#{archive.domain}/_/api/chan/post/?board=#{boardID}&num=#{postID}"
|
||||
return '' unless Redirect.securityCheck URL
|
||||
URL.archive = archive
|
||||
URL
|
||||
|
||||
@ -76,10 +76,14 @@ Redirect =
|
||||
"#{boardID}/?task=search2&search_#{if type is 'image' then 'media_hash' else type}=#{value}"
|
||||
"#{Redirect.protocol archive}#{archive.domain}/#{path}"
|
||||
|
||||
securityCheck: (URL) ->
|
||||
/^https:\/\//.test(URL) or
|
||||
location.protocol is 'http:' or
|
||||
Conf['Allow Mixed Content from Archives']
|
||||
|
||||
navigate: (URL, alternative) ->
|
||||
if URL and (
|
||||
/^https:\/\//.test(URL) or
|
||||
location.protocol is 'http:' or
|
||||
Redirect.securityCheck(URL) or
|
||||
confirm "Redirect to #{URL}?\n\nYour connection will not be encrypted."
|
||||
)
|
||||
location.replace URL
|
||||
|
||||
@ -29,6 +29,10 @@ Config =
|
||||
true
|
||||
'Redirect dead threads and images.'
|
||||
]
|
||||
'Allow Mixed Content from Archives': [
|
||||
false
|
||||
'Permit warningless access to HTTP-only archives from HTTPS pages.'
|
||||
]
|
||||
'Keybinds': [
|
||||
true
|
||||
'Bind actions to keyboard shortcuts.'
|
||||
|
||||
@ -1,46 +1,73 @@
|
||||
CrossOrigin = do ->
|
||||
CrossOrigin =
|
||||
file: do ->
|
||||
makeBlob = (urlBlob, contentType, contentDisposition, url) ->
|
||||
name = url.match(/([^\/]+)\/*$/)?[1]
|
||||
mime = contentType?.match(/[^;]*/)[0] or 'application/octet-stream'
|
||||
match =
|
||||
contentDisposition?.match(/\bfilename\s*=\s*"((\\"|[^"])+)"/i)?[1] or
|
||||
contentType?.match(/\bname\s*=\s*"((\\"|[^"])+)"/i)?[1]
|
||||
if match
|
||||
name = match.replace /\\"/g, '"'
|
||||
blob = new Blob([urlBlob], {type: mime})
|
||||
blob.name = name
|
||||
blob
|
||||
|
||||
makeBlob = (urlBlob, contentType, contentDisposition, url) ->
|
||||
name = url.match(/([^\/]+)\/*$/)?[1]
|
||||
mime = contentType?.match(/[^;]*/)[0] or 'application/octet-stream'
|
||||
match =
|
||||
contentDisposition?.match(/\bfilename\s*=\s*"((\\"|[^"])+)"/i)?[1] or
|
||||
contentType?.match(/\bname\s*=\s*"((\\"|[^"])+)"/i)?[1]
|
||||
if match
|
||||
name = match.replace /\\"/g, '"'
|
||||
blob = new Blob([urlBlob], {type: mime})
|
||||
blob.name = name
|
||||
blob
|
||||
(url, cb) ->
|
||||
<% if (type === 'crx') { %>
|
||||
$.ajax url,
|
||||
responseType: 'blob'
|
||||
onload: ->
|
||||
return cb null unless @readyState is @DONE and @status is 200
|
||||
contentType = @getResponseHeader 'Content-Type'
|
||||
contentDisposition = @getResponseHeader 'Content-Disposition'
|
||||
cb (makeBlob @response, contentType, contentDisposition, url)
|
||||
onerror: ->
|
||||
cb null
|
||||
<% } %>
|
||||
<% if (type === 'userscript') { %>
|
||||
GM_xmlhttpRequest
|
||||
method: "GET"
|
||||
url: url
|
||||
overrideMimeType: "text/plain; charset=x-user-defined"
|
||||
onload: (xhr) ->
|
||||
r = xhr.responseText
|
||||
data = new Uint8Array r.length
|
||||
i = 0
|
||||
while i < r.length
|
||||
data[i] = r.charCodeAt i
|
||||
i++
|
||||
contentType = xhr.responseHeaders.match(/Content-Type:\s*(.*)/i)?[1]
|
||||
contentDisposition = xhr.responseHeaders.match(/Content-Disposition:\s*(.*)/i)?[1]
|
||||
cb (makeBlob data, contentType, contentDisposition, url)
|
||||
onerror: ->
|
||||
cb null
|
||||
<% } %>
|
||||
|
||||
file = (url, cb) ->
|
||||
<% if (type === 'crx') { %>
|
||||
$.ajax url,
|
||||
responseType: 'blob'
|
||||
onload: ->
|
||||
return cb null unless @readyState is @DONE and @status is 200
|
||||
contentType = @getResponseHeader 'Content-Type'
|
||||
contentDisposition = @getResponseHeader 'Content-Disposition'
|
||||
cb (makeBlob @response, contentType, contentDisposition, url)
|
||||
onerror: ->
|
||||
cb null
|
||||
<% } %>
|
||||
<% if (type === 'userscript') { %>
|
||||
GM_xmlhttpRequest
|
||||
method: "GET"
|
||||
url: url
|
||||
overrideMimeType: "text/plain; charset=x-user-defined"
|
||||
onload: (xhr) ->
|
||||
r = xhr.responseText
|
||||
data = new Uint8Array r.length
|
||||
i = 0
|
||||
while i < r.length
|
||||
data[i] = r.charCodeAt i
|
||||
i++
|
||||
contentType = xhr.responseHeaders.match(/Content-Type:\s*(.*)/i)?[1]
|
||||
contentDisposition = xhr.responseHeaders.match(/Content-Disposition:\s*(.*)/i)?[1]
|
||||
cb (makeBlob data, contentType, contentDisposition, url)
|
||||
onerror: ->
|
||||
cb null
|
||||
<% } %>
|
||||
|
||||
{file}
|
||||
json: do ->
|
||||
callbacks = {}
|
||||
responses = {}
|
||||
(url, cb) ->
|
||||
<% if (type === 'crx') { %>
|
||||
$.cache url, (-> cb @response), responseType: 'json'
|
||||
<% } %>
|
||||
<% if (type === 'userscript') { %>
|
||||
if responses[url]
|
||||
cb responses[url]
|
||||
return
|
||||
if callbacks[url]
|
||||
callbacks[url].push cb
|
||||
return
|
||||
callbacks[url] = [cb]
|
||||
GM_xmlhttpRequest
|
||||
method: "GET"
|
||||
url: url
|
||||
onload: (xhr) ->
|
||||
response = JSON.parse xhr.responseText
|
||||
cb response for cb in callbacks[url]
|
||||
delete callbacks[url]
|
||||
responses[url] = response
|
||||
onerror: ->
|
||||
delete callbacks[url]
|
||||
onabort: ->
|
||||
delete callbacks[url]
|
||||
<% } %>
|
||||
|
||||
@ -132,20 +132,25 @@ Get =
|
||||
Get.insert post, root, context
|
||||
archivedPost: (boardID, postID, root, context) ->
|
||||
return false unless url = Redirect.to 'post', {boardID, postID}
|
||||
$.cache url,
|
||||
-> Get.parseArchivedPost @, boardID, postID, root, context
|
||||
,
|
||||
responseType: 'json'
|
||||
withCredentials: url.archive.withCredentials
|
||||
return true
|
||||
parseArchivedPost: (req, boardID, postID, root, context) ->
|
||||
if /^https:\/\//.test(URL) or location.protocol is 'http:'
|
||||
$.cache url,
|
||||
-> Get.parseArchivedPost @response, boardID, postID, root, context
|
||||
,
|
||||
responseType: 'json'
|
||||
withCredentials: url.archive.withCredentials
|
||||
return true
|
||||
else if Conf['Allow Mixed Content from Archives']
|
||||
CrossOrigin.json url, (response) ->
|
||||
Get.parseArchivedPost response, boardID, postID, root, context
|
||||
return true
|
||||
return false
|
||||
parseArchivedPost: (data, boardID, postID, root, context) ->
|
||||
# In case of multiple callbacks for the same request,
|
||||
# don't parse the same original post more than once.
|
||||
if post = g.posts["#{boardID}.#{postID}"]
|
||||
Get.insert post, root, context
|
||||
return
|
||||
|
||||
data = req.response
|
||||
if data.error
|
||||
$.addClass root, 'warning'
|
||||
root.textContent = data.error
|
||||
|
||||
@ -12,7 +12,7 @@ ImageCommon =
|
||||
URL = Redirect.to 'file',
|
||||
boardID: post.board.ID
|
||||
filename: src[src.length - 1]
|
||||
unless URL and (/^https:\/\//.test(URL) or location.protocol is 'http:')
|
||||
unless URL and Redirect.securityCheck URL
|
||||
URL = null
|
||||
|
||||
return cb URL if (post.isDead or post.file.isDead) and file.src.split('/')[2] is 'i.4cdn.org'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user