Bunch of changes inspired by r00k
This commit is contained in:
226
vim/bundle/webapi-vim/autoload/webapi/atom.vim
Normal file
226
vim/bundle/webapi-vim/autoload/webapi/atom.vim
Normal file
@@ -0,0 +1,226 @@
|
||||
" atom
|
||||
" Last Change: 2010-09-10
|
||||
" Maintainer: Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
" License: This file is placed in the public domain.
|
||||
" Reference:
|
||||
" http://tools.ietf.org/rfc/rfc5023.txt
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:system = function(get(g:, 'webapi#system_function', 'system'))
|
||||
|
||||
let s:author_template = {
|
||||
\ "name": "",
|
||||
\}
|
||||
|
||||
let s:link_template = {
|
||||
\ "rel": "",
|
||||
\ "href": "",
|
||||
\}
|
||||
|
||||
let s:category_template = {
|
||||
\ "term": "",
|
||||
\ "scheme": "",
|
||||
\ "label": "",
|
||||
\}
|
||||
|
||||
let s:feed_template = {
|
||||
\ "id": "",
|
||||
\ "icon": "",
|
||||
\ "logo": "",
|
||||
\ "title": "",
|
||||
\ "link": [],
|
||||
\ "category": [],
|
||||
\ "author": [],
|
||||
\ "contirubutor": [],
|
||||
\ "entry": [],
|
||||
\}
|
||||
|
||||
let s:entry_template = {
|
||||
\ "id": "",
|
||||
\ "icon": "",
|
||||
\ "logo": "",
|
||||
\ "title": "",
|
||||
\ "link": [],
|
||||
\ "category": [],
|
||||
\ "author": [],
|
||||
\ "contirubutor": [],
|
||||
\ "copyright": "",
|
||||
\ "content": "",
|
||||
\ "content.type": "text/plain",
|
||||
\ "content.mode": "escaped",
|
||||
\ "summary": "",
|
||||
\ "created": "",
|
||||
\ "updated": "",
|
||||
\}
|
||||
|
||||
for s:name in ['author', 'link', 'category', 'feed', 'entry']
|
||||
for s:key in keys(eval('s:'.s:name.'_template'))
|
||||
let key = substitute(s:key, '\.\(.\)', '\=toupper(submatch(1))', '')
|
||||
exe "function s:".s:name."_template.set".toupper(key[0]).key[1:]."(v) dict\n"
|
||||
\. " let self['".s:key."'] = a:v\n"
|
||||
\. "endfunction\n"
|
||||
exe "function s:".s:name."_template.get".toupper(key[0]).key[1:]."() dict\n"
|
||||
\. " return self['".s:key."']\n"
|
||||
\. "endfunction\n"
|
||||
endfor
|
||||
endfor
|
||||
function s:entry_template.setContentFromFile(file) dict
|
||||
let quote = &shellxquote == '"' ? "'" : '"'
|
||||
let bits = substitute(s:system("xxd -ps ".quote.file.quote), "[ \n\r]", '', 'g')
|
||||
let self['mode'] = "base64"
|
||||
let self['content'] = webapi#base64#b64encodebin(bits)
|
||||
endfunction
|
||||
|
||||
unlet s:name
|
||||
unlet s:key
|
||||
|
||||
function! webapi#atom#newEntry()
|
||||
return deepcopy(s:entry_template)
|
||||
endfunction
|
||||
|
||||
function! s:createXml(entry)
|
||||
let entry = webapi#xml#createElement("entry")
|
||||
let entry.attr["xmlns"] = "http://purl.org/atom/ns#"
|
||||
|
||||
for key in keys(a:entry)
|
||||
if type(a:entry[key]) == 1 && key !~ '\.'
|
||||
let node = webapi#xml#createElement(key)
|
||||
call node.value(a:entry[key])
|
||||
if key == "content"
|
||||
let node.attr["type"] = a:entry['content.type']
|
||||
let node.attr["mode"] = a:entry['content.mode']
|
||||
endif
|
||||
call add(entry.child, node)
|
||||
endif
|
||||
endfor
|
||||
let xml = '<?xml version="1.0" encoding="utf-8"?>' . entry.toString()
|
||||
return iconv(xml, &encoding, "utf-8")
|
||||
endfunction
|
||||
|
||||
function! s:createWsse(user, pass)
|
||||
let now = localtime()
|
||||
let nonce = webapi#sha1#sha1(now . " " . now)[0:28]
|
||||
let created = strftime("%Y-%m-%dT%H:%M:%SZ", now)
|
||||
let passworddigest = webapi#base64#b64encodebin(webapi#sha1#sha1(nonce.created.a:pass))
|
||||
let nonce = webapi#base64#b64encode(nonce)
|
||||
return 'UsernameToken Username="'.a:user.'", PasswordDigest="'.passworddigest.'", Nonce="'.nonce.'", Created="'.created.'"'
|
||||
endfunction
|
||||
|
||||
function! webapi#atom#deleteEntry(uri, user, pass)
|
||||
let res = webapi#http#post(a:uri, "",
|
||||
\ {
|
||||
\ "Content-Type": "application/x.atom+xml",
|
||||
\ "X-WSSE": s:createWsse(a:user, a:pass)
|
||||
\ }, "DELETE")
|
||||
return res
|
||||
endfunction
|
||||
|
||||
function! webapi#atom#updateEntry(uri, user, pass, entry, ...)
|
||||
let headdata = a:0 > 0 ? a:000[0] : {}
|
||||
let headdata["Content-Type"] = "application/x.atom+xml"
|
||||
let headdata["X-WSSE"] = s:createWsse(a:user, a:pass)
|
||||
let res = webapi#http#post(a:uri, s:createXml(a:entry), headdata, "PUT")
|
||||
let location = filter(res.header, 'v:val =~ "^Location:"')
|
||||
if len(location)
|
||||
return split(location[0], '\s*:\s\+')[1]
|
||||
endif
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! webapi#atom#createEntry(uri, user, pass, entry, ...)
|
||||
let headdata = a:0 > 0 ? a:000[0] : {}
|
||||
let headdata["Content-Type"] = "application/x.atom+xml"
|
||||
let headdata["X-WSSE"] = s:createWsse(a:user, a:pass)
|
||||
let headdata["WWW-Authenticate"] = "WSSE profile=\"UsernameToken\""
|
||||
let res = webapi#http#post(a:uri, s:createXml(a:entry), headdata, "POST")
|
||||
let location = filter(res.header, 'v:val =~ "^Location:"')
|
||||
if len(location)
|
||||
return split(location[0], '\s*:\s\+')[1]
|
||||
endif
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
function! s:parse_node(target, parent)
|
||||
for node in a:parent.child
|
||||
if type(node) != 4 || !has_key(a:target, node.name)
|
||||
unlet node
|
||||
continue
|
||||
endif
|
||||
if node.name == 'content'
|
||||
let a:target[node.name] = node.value()
|
||||
if has_key(node.attr, 'type')
|
||||
let a:target['content.type'] = node.attr['type']
|
||||
endif
|
||||
if has_key(node.attr, 'type')
|
||||
let a:target['content.type'] = node.attr['type']
|
||||
endif
|
||||
elseif node.name == 'link'
|
||||
let link = deepcopy(s:link_template)
|
||||
for attr in keys(node.attr)
|
||||
if !has_key(link, attr)
|
||||
continue
|
||||
endif
|
||||
let link[attr] = node.attr[attr]
|
||||
endfor
|
||||
call add(a:target.link, link)
|
||||
elseif node.name == 'author'
|
||||
let author = deepcopy(s:author_template)
|
||||
for item in node.child
|
||||
if type(item) == 4 && has_key(author, item.name)
|
||||
let author[item.name] = item.value()
|
||||
endif
|
||||
unlet item
|
||||
endfor
|
||||
call add(a:target.author, author)
|
||||
elseif node.name == 'entry'
|
||||
let entry = deepcopy(s:entry_template)
|
||||
call s:parse_node(entry, node)
|
||||
call add(a:target.entry, entry)
|
||||
elseif type(a:target[node.name]) == 3
|
||||
call add(a:target[node.name], parent.value())
|
||||
else
|
||||
let a:target[node.name] = node.value()
|
||||
endif
|
||||
unlet node
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! webapi#atom#getFeed(uri, user, pass)
|
||||
let headdata = {}
|
||||
if len(a:user) > 0 && len(a:pass) > 0
|
||||
let headdata["X-WSSE"] = s:createWsse(a:user, a:pass)
|
||||
endif
|
||||
let res = webapi#http#get(a:uri, {}, headdata)
|
||||
let dom = webapi#xml#parse(res.content)
|
||||
let feed = deepcopy(s:feed_template)
|
||||
call s:parse_node(feed, dom)
|
||||
return feed
|
||||
endfunction
|
||||
|
||||
function! webapi#atom#getService(uri, user, pass)
|
||||
let headdata = {}
|
||||
if len(a:user) > 0 && len(a:pass) > 0
|
||||
let headdata["X-WSSE"] = s:createWsse(a:user, a:pass)
|
||||
endif
|
||||
let res = webapi#http#get(a:uri, {}, headdata)
|
||||
return webapi#xml#parse(res.content)
|
||||
endfunction
|
||||
|
||||
function! webapi#atom#getEntry(uri, user, pass)
|
||||
let headdata = {}
|
||||
if len(a:user) > 0 && len(a:pass) > 0
|
||||
let headdata["X-WSSE"] = s:createWsse(a:user, a:pass)
|
||||
endif
|
||||
let res = webapi#http#get(a:uri, {}, headdata)
|
||||
let dom = webapi#xml#parse(res.content)
|
||||
let entry = deepcopy(s:entry_template)
|
||||
call s:parse_node(entry, dom)
|
||||
return entry
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
||||
140
vim/bundle/webapi-vim/autoload/webapi/base64.vim
Normal file
140
vim/bundle/webapi-vim/autoload/webapi/base64.vim
Normal file
@@ -0,0 +1,140 @@
|
||||
" base64 codec
|
||||
" Last Change: 2010-07-25
|
||||
" Maintainer: Yukihiro Nakadaira <yukihiro.nakadaira@gmail.com>
|
||||
" License: This file is placed in the public domain.
|
||||
" Reference:
|
||||
" [The Base16, Base32, and Base64 Data Encodings]
|
||||
" http://tools.ietf.org/rfc/rfc3548.txt
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! webapi#base64#b64encode(data)
|
||||
let b64 = s:b64encode(s:str2bytes(a:data), s:standard_table, '=')
|
||||
return join(b64, '')
|
||||
endfunction
|
||||
|
||||
function! webapi#base64#b64encodebin(data)
|
||||
let b64 = s:b64encode(s:binstr2bytes(a:data), s:standard_table, '=')
|
||||
return join(b64, '')
|
||||
endfunction
|
||||
|
||||
function! webapi#base64#b64decode(data)
|
||||
let bytes = s:b64decode(split(a:data, '\zs'), s:standard_table, '=')
|
||||
return s:bytes2str(bytes)
|
||||
endfunction
|
||||
|
||||
function! webapi#base64#test()
|
||||
if webapi#base64#b64encode("hello, world") ==# "aGVsbG8sIHdvcmxk"
|
||||
echo "test1: ok"
|
||||
else
|
||||
echoerr "test1: failed"
|
||||
endif
|
||||
if webapi#base64#b64encode("hello, worldx") ==# "aGVsbG8sIHdvcmxkeA=="
|
||||
echo "test2: ok"
|
||||
else
|
||||
echoerr "test2: failed"
|
||||
endif
|
||||
if webapi#base64#b64encode("hello, worldxx") ==# "aGVsbG8sIHdvcmxkeHg="
|
||||
echo "test3: ok"
|
||||
else
|
||||
echoerr "test3: falied"
|
||||
endif
|
||||
if webapi#base64#b64encode("hello, worldxxx") ==# "aGVsbG8sIHdvcmxkeHh4"
|
||||
echo "test4: ok"
|
||||
else
|
||||
echoerr "test4: falied"
|
||||
endif
|
||||
if webapi#base64#b64decode(webapi#base64#b64encode("hello, world")) ==# "hello, world"
|
||||
echo "test5: ok"
|
||||
else
|
||||
echoerr "test5: failed"
|
||||
endif
|
||||
if webapi#base64#b64decode(webapi#base64#b64encode("hello, worldx")) ==# "hello, worldx"
|
||||
echo "test6: ok"
|
||||
else
|
||||
echoerr "test6: failed"
|
||||
endif
|
||||
if webapi#base64#b64decode(webapi#base64#b64encode("hello, worldxx")) ==# "hello, worldxx"
|
||||
echo "test7: ok"
|
||||
else
|
||||
echoerr "test7: failed"
|
||||
endif
|
||||
if webapi#base64#b64decode(webapi#base64#b64encode("hello, worldxxx")) ==# "hello, worldxxx"
|
||||
echo "test8: ok"
|
||||
else
|
||||
echoerr "test8: failed"
|
||||
endif
|
||||
endfunction
|
||||
|
||||
let s:standard_table = [
|
||||
\ "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P",
|
||||
\ "Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f",
|
||||
\ "g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v",
|
||||
\ "w","x","y","z","0","1","2","3","4","5","6","7","8","9","+","/"]
|
||||
|
||||
let s:urlsafe_table = [
|
||||
\ "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P",
|
||||
\ "Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f",
|
||||
\ "g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v",
|
||||
\ "w","x","y","z","0","1","2","3","4","5","6","7","8","9","-","_"]
|
||||
|
||||
function! s:b64encode(bytes, table, pad)
|
||||
let b64 = []
|
||||
for i in range(0, len(a:bytes) - 1, 3)
|
||||
let n = a:bytes[i] * 0x10000
|
||||
\ + get(a:bytes, i + 1, 0) * 0x100
|
||||
\ + get(a:bytes, i + 2, 0)
|
||||
call add(b64, a:table[n / 0x40000])
|
||||
call add(b64, a:table[n / 0x1000 % 0x40])
|
||||
call add(b64, a:table[n / 0x40 % 0x40])
|
||||
call add(b64, a:table[n % 0x40])
|
||||
endfor
|
||||
if len(a:bytes) % 3 == 1
|
||||
let b64[-1] = a:pad
|
||||
let b64[-2] = a:pad
|
||||
endif
|
||||
if len(a:bytes) % 3 == 2
|
||||
let b64[-1] = a:pad
|
||||
endif
|
||||
return b64
|
||||
endfunction
|
||||
|
||||
function! s:b64decode(b64, table, pad)
|
||||
let a2i = {}
|
||||
for i in range(len(a:table))
|
||||
let a2i[a:table[i]] = i
|
||||
endfor
|
||||
let bytes = []
|
||||
for i in range(0, len(a:b64) - 1, 4)
|
||||
let n = a2i[a:b64[i]] * 0x40000
|
||||
\ + a2i[a:b64[i + 1]] * 0x1000
|
||||
\ + (a:b64[i + 2] == a:pad ? 0 : a2i[a:b64[i + 2]]) * 0x40
|
||||
\ + (a:b64[i + 3] == a:pad ? 0 : a2i[a:b64[i + 3]])
|
||||
call add(bytes, n / 0x10000)
|
||||
call add(bytes, n / 0x100 % 0x100)
|
||||
call add(bytes, n % 0x100)
|
||||
endfor
|
||||
if a:b64[-1] == a:pad
|
||||
unlet a:b64[-1]
|
||||
endif
|
||||
if a:b64[-2] == a:pad
|
||||
unlet a:b64[-1]
|
||||
endif
|
||||
return bytes
|
||||
endfunction
|
||||
|
||||
function! s:binstr2bytes(str)
|
||||
return map(range(len(a:str)/2), 'eval("0x".a:str[v:val*2 : v:val*2+1])')
|
||||
endfunction
|
||||
|
||||
function! s:str2bytes(str)
|
||||
return map(range(len(a:str)), 'char2nr(a:str[v:val])')
|
||||
endfunction
|
||||
|
||||
function! s:bytes2str(bytes)
|
||||
return eval('"' . join(map(copy(a:bytes), 'printf(''\x%02x'', v:val)'), '') . '"')
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
56
vim/bundle/webapi-vim/autoload/webapi/bit.vim
Normal file
56
vim/bundle/webapi-vim/autoload/webapi/bit.vim
Normal file
@@ -0,0 +1,56 @@
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! webapi#bit#dec2bin(v)
|
||||
let v = a:v
|
||||
if v == 0 | return 0 | endif
|
||||
let ret = ""
|
||||
while v > 0
|
||||
let i = v % 2
|
||||
let ret = i . ret
|
||||
let v = v / 2
|
||||
endwhile
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! webapi#bit#bin2dec(v)
|
||||
let v = a:v
|
||||
if len(v) == 0 | return 0 | endif
|
||||
let i = 1
|
||||
let ret = ""
|
||||
for n in reverse(split(v, '\zs'))
|
||||
if n == 1
|
||||
let ret = ret + i
|
||||
endif
|
||||
let i = i * 2
|
||||
endfor
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! webapi#bit#or(a,b)
|
||||
let a = webapi#bit#dec2bin(a:a)
|
||||
let b = webapi#bit#dec2bin(a:b)
|
||||
return webapi#bit#bin2dec(tr((a + b), '2', '1'))
|
||||
endfunction
|
||||
|
||||
function! webapi#bit#and(a,b)
|
||||
let a = webapi#bit#dec2bin(a:a)
|
||||
let b = webapi#bit#dec2bin(a:b)
|
||||
return webapi#bit#bin2dec(tr((a + b), '21', '10'))
|
||||
endfunction
|
||||
|
||||
function! webapi#bit#shift(a,b)
|
||||
let a = webapi#bit#dec2bin(a:a)
|
||||
let a = repeat('0', 32-len(a)) . a
|
||||
if a:b < 0
|
||||
let a = (repeat('0', -a:b) . a[: a:b-1])[-32:]
|
||||
elseif a:b > 0
|
||||
let a = (a . repeat('0', a:b))[-32:]
|
||||
endif
|
||||
return webapi#bit#bin2dec(a)
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
||||
53
vim/bundle/webapi-vim/autoload/webapi/feed.vim
Normal file
53
vim/bundle/webapi-vim/autoload/webapi/feed.vim
Normal file
@@ -0,0 +1,53 @@
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! s:attr(node, name)
|
||||
let n = a:node.childNode(a:name)
|
||||
if empty(n)
|
||||
return ""
|
||||
endif
|
||||
return n.value()
|
||||
endfunction
|
||||
|
||||
function! webapi#feed#parseURL(url)
|
||||
let dom = webapi#xml#parseURL(a:url)
|
||||
let items = []
|
||||
if dom.name == 'rss'
|
||||
let channel = dom.childNode('channel')
|
||||
for item in channel.childNodes('item')
|
||||
call add(items, {
|
||||
\ "title": s:attr(item, 'title'),
|
||||
\ "link": s:attr(item, 'link'),
|
||||
\ "content": s:attr(item, 'description'),
|
||||
\ "id": s:attr(item, 'guid'),
|
||||
\ "date": s:attr(item, 'pubDate'),
|
||||
\})
|
||||
endfor
|
||||
elseif dom.name == 'rdf:RDF'
|
||||
for item in dom.childNodes('item')
|
||||
call add(items, {
|
||||
\ "title": s:attr(item, 'title'),
|
||||
\ "link": s:attr(item, 'link'),
|
||||
\ "content": s:attr(item, 'description'),
|
||||
\ "id": s:attr(item, 'guid'),
|
||||
\ "date": s:attr(item, 'dc:date'),
|
||||
\})
|
||||
endfor
|
||||
elseif dom.name == 'feed'
|
||||
for item in dom.childNodes('entry')
|
||||
call add(items, {
|
||||
\ "title": s:attr(item, 'title'),
|
||||
\ "link": item.childNode('link').attr['href'],
|
||||
\ "content": s:attr(item, 'content'),
|
||||
\ "id": s:attr(item, 'id'),
|
||||
\ "date": s:attr(item, 'updated'),
|
||||
\})
|
||||
endfor
|
||||
endif
|
||||
return items
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
||||
166
vim/bundle/webapi-vim/autoload/webapi/hmac.vim
Normal file
166
vim/bundle/webapi-vim/autoload/webapi/hmac.vim
Normal file
@@ -0,0 +1,166 @@
|
||||
" This is a port of rfc2104 hmac function.
|
||||
" http://www.ietf.org/rfc/rfc2104.txt
|
||||
" Last Change: 2010-02-13
|
||||
" Maintainer: Yukihiro Nakadaira <yukihiro.nakadaira@gmail.com>
|
||||
" License: This file is placed in the public domain.
|
||||
|
||||
" @param mixed key List or String
|
||||
" @param mixed text List or String
|
||||
" @param Funcref hash function digest_hex(key:List, text:List):String
|
||||
" @param Number blocksize
|
||||
function webapi#hmac#hmac(key, text, hash, blocksize)
|
||||
let key = (type(a:key) == type("")) ? s:str2bytes(a:key) : a:key
|
||||
let text = (type(a:text) == type("")) ? s:str2bytes(a:text) : a:text
|
||||
return s:Hmac(key, text, a:hash, a:blocksize)
|
||||
endfunction
|
||||
|
||||
function webapi#hmac#md5(key, text)
|
||||
return webapi#hmac#hmac(a:key, a:text, 'webapi#md5#md5bin', 64)
|
||||
endfunction
|
||||
|
||||
function webapi#hmac#sha1(key, text)
|
||||
return webapi#hmac#hmac(a:key, a:text, 'webapi#sha1#sha1bin', 64)
|
||||
endfunction
|
||||
|
||||
" http://www.ietf.org/rfc/rfc2202.txt
|
||||
" Test Cases for HMAC-MD5 and HMAC-SHA-1
|
||||
function webapi#hmac#test()
|
||||
" Test Cases for HMAC-MD5
|
||||
call s:test("md5: 1", "webapi#hmac#md5",
|
||||
\ repeat("\x0b", 16),
|
||||
\ "Hi There",
|
||||
\ "9294727a3638bb1c13f48ef8158bfc9d")
|
||||
call s:test("md5: 2", "webapi#hmac#md5",
|
||||
\ "Jefe",
|
||||
\ "what do ya want for nothing?",
|
||||
\ "750c783e6ab0b503eaa86e310a5db738")
|
||||
call s:test("md5: 3", "webapi#hmac#md5",
|
||||
\ repeat("\xaa", 16),
|
||||
\ repeat("\xdd", 50),
|
||||
\ "56be34521d144c88dbb8c733f0e8b3f6")
|
||||
call s:test("md5: 4", "webapi#hmac#md5",
|
||||
\ s:hex2bytes("0102030405060708090a0b0c0d0e0f10111213141516171819"),
|
||||
\ repeat([0xcd], 50),
|
||||
\ "697eaf0aca3a3aea3a75164746ffaa79")
|
||||
call s:test("md5: 5", "webapi#hmac#md5",
|
||||
\ repeat("\x0c", 16),
|
||||
\ "Test With Truncation",
|
||||
\ "56461ef2342edc00f9bab995690efd4c")
|
||||
call s:test("md5: 6", "webapi#hmac#md5",
|
||||
\ repeat("\xaa", 80),
|
||||
\ "Test Using Larger Than Block-Size Key - Hash Key First",
|
||||
\ "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd")
|
||||
call s:test("md5: 7", "webapi#hmac#md5",
|
||||
\ repeat("\xaa", 80),
|
||||
\ "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
|
||||
\ "6f630fad67cda0ee1fb1f562db3aa53e")
|
||||
|
||||
" Test Cases for HMAC-SHA1
|
||||
call s:test("sha1: 1", "webapi#hmac#sha1",
|
||||
\ repeat("\x0b", 20),
|
||||
\ "Hi There",
|
||||
\ "b617318655057264e28bc0b6fb378c8ef146be00")
|
||||
call s:test("sha1: 2", "webapi#hmac#sha1",
|
||||
\ "Jefe",
|
||||
\ "what do ya want for nothing?",
|
||||
\ "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79")
|
||||
call s:test("sha1: 3", "webapi#hmac#sha1",
|
||||
\ repeat("\xaa", 20),
|
||||
\ repeat("\xdd", 50),
|
||||
\ "125d7342b9ac11cd91a39af48aa17b4f63f175d3")
|
||||
call s:test("sha1: 4", "webapi#hmac#sha1",
|
||||
\ s:hex2bytes("0102030405060708090a0b0c0d0e0f10111213141516171819"),
|
||||
\ repeat([0xcd], 50),
|
||||
\ "4c9007f4026250c6bc8414f9bf50c86c2d7235da")
|
||||
call s:test("sha1: 5", "webapi#hmac#sha1",
|
||||
\ repeat("\x0c", 20),
|
||||
\ "Test With Truncation",
|
||||
\ "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04")
|
||||
call s:test("sha1: 6", "webapi#hmac#sha1",
|
||||
\ repeat("\xaa", 80),
|
||||
\ "Test Using Larger Than Block-Size Key - Hash Key First",
|
||||
\ "aa4ae5e15272d00e95705637ce8a3b55ed402112")
|
||||
call s:test("sha1: 7", "webapi#hmac#sha1",
|
||||
\ repeat("\xaa", 80),
|
||||
\ "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
|
||||
\ "e8e99d0f45237d786d6bbaa7965c7808bbff1a91")
|
||||
endfunction
|
||||
|
||||
function s:test(name, func, key, data, digest)
|
||||
let result = call(a:func, [a:key, a:data])
|
||||
echo "test_case:" a:name
|
||||
echo "expect:" a:digest
|
||||
echo "result:" result
|
||||
if a:digest ==? result
|
||||
echo "test: OK"
|
||||
else
|
||||
echohl Error
|
||||
echo "test: NG"
|
||||
echohl None
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" @param List key
|
||||
" @param List text
|
||||
" @param Funcref hash
|
||||
" @param Number blocksize
|
||||
function! s:Hmac(key, text, hash, blocksize)
|
||||
let key = a:key
|
||||
if len(key) > a:blocksize
|
||||
let key = s:hex2bytes(call(a:hash, [key]))
|
||||
endif
|
||||
let k_ipad = repeat([0], a:blocksize)
|
||||
let k_opad = repeat([0], a:blocksize)
|
||||
for i in range(a:blocksize)
|
||||
let k_ipad[i] = s:bitwise_xor(get(key, i, 0), 0x36)
|
||||
let k_opad[i] = s:bitwise_xor(get(key, i, 0), 0x5c)
|
||||
endfor
|
||||
let hash1 = s:hex2bytes(call(a:hash, [k_ipad + a:text]))
|
||||
let hmac = call(a:hash, [k_opad + hash1])
|
||||
return hmac
|
||||
endfunction
|
||||
|
||||
function! s:str2bytes(str)
|
||||
return map(range(len(a:str)), 'char2nr(a:str[v:val])')
|
||||
endfunction
|
||||
|
||||
function! s:hex2bytes(str)
|
||||
return map(split(a:str, '..\zs'), 'str2nr(v:val, 16)')
|
||||
endfunction
|
||||
|
||||
let s:xor = [
|
||||
\ [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF],
|
||||
\ [0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xB, 0xA, 0xD, 0xC, 0xF, 0xE],
|
||||
\ [0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xA, 0xB, 0x8, 0x9, 0xE, 0xF, 0xC, 0xD],
|
||||
\ [0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xB, 0xA, 0x9, 0x8, 0xF, 0xE, 0xD, 0xC],
|
||||
\ [0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xC, 0xD, 0xE, 0xF, 0x8, 0x9, 0xA, 0xB],
|
||||
\ [0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xD, 0xC, 0xF, 0xE, 0x9, 0x8, 0xB, 0xA],
|
||||
\ [0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xE, 0xF, 0xC, 0xD, 0xA, 0xB, 0x8, 0x9],
|
||||
\ [0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xF, 0xE, 0xD, 0xC, 0xB, 0xA, 0x9, 0x8],
|
||||
\ [0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7],
|
||||
\ [0x9, 0x8, 0xB, 0xA, 0xD, 0xC, 0xF, 0xE, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6],
|
||||
\ [0xA, 0xB, 0x8, 0x9, 0xE, 0xF, 0xC, 0xD, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5],
|
||||
\ [0xB, 0xA, 0x9, 0x8, 0xF, 0xE, 0xD, 0xC, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4],
|
||||
\ [0xC, 0xD, 0xE, 0xF, 0x8, 0x9, 0xA, 0xB, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3],
|
||||
\ [0xD, 0xC, 0xF, 0xE, 0x9, 0x8, 0xB, 0xA, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2],
|
||||
\ [0xE, 0xF, 0xC, 0xD, 0xA, 0xB, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1],
|
||||
\ [0xF, 0xE, 0xD, 0xC, 0xB, 0xA, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0]
|
||||
\ ]
|
||||
|
||||
function! s:bitwise_xor(a, b)
|
||||
let a = a:a < 0 ? a:a - 0x80000000 : a:a
|
||||
let b = a:b < 0 ? a:b - 0x80000000 : a:b
|
||||
let r = 0
|
||||
let n = 1
|
||||
while a || b
|
||||
let r += s:xor[a % 0x10][b % 0x10] * n
|
||||
let a = a / 0x10
|
||||
let b = b / 0x10
|
||||
let n = n * 0x10
|
||||
endwhile
|
||||
if (a:a < 0) != (a:b < 0)
|
||||
let r += 0x80000000
|
||||
endif
|
||||
return r
|
||||
endfunction
|
||||
|
||||
74
vim/bundle/webapi-vim/autoload/webapi/html.vim
Normal file
74
vim/bundle/webapi-vim/autoload/webapi/html.vim
Normal file
@@ -0,0 +1,74 @@
|
||||
" html
|
||||
" Last Change: 2010-09-10
|
||||
" Maintainer: Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
" License: This file is placed in the public domain.
|
||||
" Reference:
|
||||
"
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! s:nr2byte(nr)
|
||||
if a:nr < 0x80
|
||||
return nr2char(a:nr)
|
||||
elseif a:nr < 0x800
|
||||
return nr2char(a:nr/64+192).nr2char(a:nr%64+128)
|
||||
else
|
||||
return nr2char(a:nr/4096%16+224).nr2char(a:nr/64%64+128).nr2char(a:nr%64+128)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:nr2enc_char(charcode)
|
||||
if &encoding == 'utf-8'
|
||||
return nr2char(a:charcode)
|
||||
endif
|
||||
let char = s:nr2byte(a:charcode)
|
||||
if strlen(char) > 1
|
||||
let char = strtrans(iconv(char, 'utf-8', &encoding))
|
||||
endif
|
||||
return char
|
||||
endfunction
|
||||
|
||||
function! webapi#html#decodeEntityReference(str)
|
||||
let str = a:str
|
||||
let str = substitute(str, '>', '>', 'g')
|
||||
let str = substitute(str, '<', '<', 'g')
|
||||
let str = substitute(str, '"', '"', 'g')
|
||||
let str = substitute(str, ''', "'", 'g')
|
||||
let str = substitute(str, ' ', ' ', 'g')
|
||||
let str = substitute(str, '¥', '\¥', 'g')
|
||||
let str = substitute(str, '&#\(\d\+\);', '\=s:nr2enc_char(submatch(1))', 'g')
|
||||
let str = substitute(str, '&', '\&', 'g')
|
||||
let str = substitute(str, '»', '>', 'g')
|
||||
let str = substitute(str, '«', '<', 'g')
|
||||
return str
|
||||
endfunction
|
||||
|
||||
function! webapi#html#encodeEntityReference(str)
|
||||
let str = a:str
|
||||
let str = substitute(str, '&', '\&', 'g')
|
||||
let str = substitute(str, '>', '\>', 'g')
|
||||
let str = substitute(str, '<', '\<', 'g')
|
||||
let str = substitute(str, "\n", '\
', 'g')
|
||||
let str = substitute(str, '"', '\"', 'g')
|
||||
let str = substitute(str, "'", '\'', 'g')
|
||||
let str = substitute(str, ' ', '\ ', 'g')
|
||||
return str
|
||||
endfunction
|
||||
|
||||
function! webapi#html#parse(html)
|
||||
let html = substitute(a:html, '<\(area\|base\|basefont\|br\|nobr\|col\|frame\|hr\|img\|input\|isindex\|link\|meta\|param\|embed\|keygen\|command\)\([^>]*[^/]\|\)>', '<\1\2/>', 'g')
|
||||
return webapi#xml#parse(html)
|
||||
endfunction
|
||||
|
||||
function! webapi#html#parseFile(fname)
|
||||
return webapi#html#parse(join(readfile(a:fname), "\n"))
|
||||
endfunction
|
||||
|
||||
function! webapi#html#parseURL(url)
|
||||
return webapi#html#parse(webapi#http#get(a:url).content)
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
||||
251
vim/bundle/webapi-vim/autoload/webapi/http.vim
Normal file
251
vim/bundle/webapi-vim/autoload/webapi/http.vim
Normal file
@@ -0,0 +1,251 @@
|
||||
" http
|
||||
" Last Change: 2010-09-10
|
||||
" Maintainer: Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
" License: This file is placed in the public domain.
|
||||
" Reference:
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:system = function(get(g:, 'webapi#system_function', 'system'))
|
||||
|
||||
function! s:nr2byte(nr)
|
||||
if a:nr < 0x80
|
||||
return nr2char(a:nr)
|
||||
elseif a:nr < 0x800
|
||||
return nr2char(a:nr/64+192).nr2char(a:nr%64+128)
|
||||
elseif a:nr < 0x10000
|
||||
return nr2char(a:nr/4096%16+224).nr2char(a:nr/64%64+128).nr2char(a:nr%64+128)
|
||||
elseif a:nr < 0x200000
|
||||
return nr2char(a:nr/262144%16+240).nr2char(a:nr/4096/16+128).nr2char(a:nr/64%64+128).nr2char(a:nr%64+128)
|
||||
elseif a:nr < 0x4000000
|
||||
return nr2char(a:nr/16777216%16+248).nr2char(a:nr/262144%16+128).nr2char(a:nr/4096/16+128).nr2char(a:nr/64%64+128).nr2char(a:nr%64+128)
|
||||
else
|
||||
return nr2char(a:nr/1073741824%16+252).nr2char(a:nr/16777216%16+128).nr2char(a:nr/262144%16+128).nr2char(a:nr/4096/16+128).nr2char(a:nr/64%64+128).nr2char(a:nr%64+128)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:nr2enc_char(charcode)
|
||||
if &encoding == 'utf-8'
|
||||
return nr2char(a:charcode)
|
||||
endif
|
||||
let char = s:nr2byte(a:charcode)
|
||||
if strlen(char) > 1
|
||||
let char = strtrans(iconv(char, 'utf-8', &encoding))
|
||||
endif
|
||||
return char
|
||||
endfunction
|
||||
|
||||
function! s:nr2hex(nr)
|
||||
let n = a:nr
|
||||
let r = ""
|
||||
while n
|
||||
let r = '0123456789ABCDEF'[n % 16] . r
|
||||
let n = n / 16
|
||||
endwhile
|
||||
return r
|
||||
endfunction
|
||||
|
||||
function! s:urlencode_char(c)
|
||||
let utf = iconv(a:c, &encoding, "utf-8")
|
||||
if utf == ""
|
||||
let utf = a:c
|
||||
endif
|
||||
let s = ""
|
||||
for i in range(strlen(utf))
|
||||
let s .= printf("%%%02X", char2nr(utf[i]))
|
||||
endfor
|
||||
return s
|
||||
endfunction
|
||||
|
||||
function! webapi#http#decodeURI(str)
|
||||
let ret = a:str
|
||||
let ret = substitute(ret, '+', ' ', 'g')
|
||||
let ret = substitute(ret, '%\(\x\x\)', '\=printf("%c", str2nr(submatch(1), 16))', 'g')
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! webapi#http#escape(str)
|
||||
return substitute(a:str, '[^a-zA-Z0-9_.~/-]', '\=s:urlencode_char(submatch(0))', 'g')
|
||||
endfunction
|
||||
|
||||
function! webapi#http#encodeURI(items)
|
||||
let ret = ''
|
||||
if type(a:items) == 4
|
||||
for key in sort(keys(a:items))
|
||||
if strlen(ret) | let ret .= "&" | endif
|
||||
let ret .= key . "=" . webapi#http#encodeURI(a:items[key])
|
||||
endfor
|
||||
elseif type(a:items) == 3
|
||||
for item in sort(a:items)
|
||||
if strlen(ret) | let ret .= "&" | endif
|
||||
let ret .= item
|
||||
endfor
|
||||
else
|
||||
let ret = substitute(a:items, '[^a-zA-Z0-9_.~-]', '\=s:urlencode_char(submatch(0))', 'g')
|
||||
endif
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! webapi#http#encodeURIComponent(items)
|
||||
let ret = ''
|
||||
if type(a:items) == 4
|
||||
for key in sort(keys(a:items))
|
||||
if strlen(ret) | let ret .= "&" | endif
|
||||
let ret .= key . "=" . webapi#http#encodeURIComponent(a:items[key])
|
||||
endfor
|
||||
elseif type(a:items) == 3
|
||||
for item in sort(a:items)
|
||||
if strlen(ret) | let ret .= "&" | endif
|
||||
let ret .= item
|
||||
endfor
|
||||
else
|
||||
let items = iconv(a:items, &enc, "utf-8")
|
||||
let len = strlen(items)
|
||||
let i = 0
|
||||
while i < len
|
||||
let ch = items[i]
|
||||
if ch =~# '[0-9A-Za-z-._~!''()*]'
|
||||
let ret .= ch
|
||||
elseif ch == ' '
|
||||
let ret .= '+'
|
||||
else
|
||||
let ret .= '%' . substitute('0' . s:nr2hex(char2nr(ch)), '^.*\(..\)$', '\1', '')
|
||||
endif
|
||||
let i = i + 1
|
||||
endwhile
|
||||
endif
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! webapi#http#get(url, ...)
|
||||
let getdata = a:0 > 0 ? a:000[0] : {}
|
||||
let headdata = a:0 > 1 ? a:000[1] : {}
|
||||
let follow = a:0 > 2 ? a:000[2] : 1
|
||||
let url = a:url
|
||||
let getdatastr = webapi#http#encodeURI(getdata)
|
||||
if strlen(getdatastr)
|
||||
let url .= "?" . getdatastr
|
||||
endif
|
||||
if executable('curl')
|
||||
let command = printf('curl %s -s -k -i', follow ? '-L' : '')
|
||||
let quote = &shellxquote == '"' ? "'" : '"'
|
||||
for key in keys(headdata)
|
||||
if has('win32')
|
||||
let command .= " -H " . quote . key . ": " . substitute(headdata[key], '"', '"""', 'g') . quote
|
||||
else
|
||||
let command .= " -H " . quote . key . ": " . headdata[key] . quote
|
||||
endif
|
||||
endfor
|
||||
let command .= " ".quote.url.quote
|
||||
let res = s:system(command)
|
||||
elseif executable('wget')
|
||||
let command = printf('wget -O- --save-headers --server-response -q %s', follow ? '-L' : '')
|
||||
let quote = &shellxquote == '"' ? "'" : '"'
|
||||
for key in keys(headdata)
|
||||
if has('win32')
|
||||
let command .= " --header=" . quote . key . ": " . substitute(headdata[key], '"', '"""', 'g') . quote
|
||||
else
|
||||
let command .= " --header=" . quote . key . ": " . headdata[key] . quote
|
||||
endif
|
||||
endfor
|
||||
let command .= " ".quote.url.quote
|
||||
let res = s:system(command)
|
||||
else
|
||||
throw "require `curl` or `wget` command"
|
||||
endif
|
||||
if follow != 0
|
||||
while res =~ '^HTTP/1.\d 3' || res =~ '^HTTP/1\.\d 200 Connection established' || res =~ '^HTTP/1\.\d 100 Continue'
|
||||
let pos = stridx(res, "\r\n\r\n")
|
||||
if pos != -1
|
||||
let res = strpart(res, pos+4)
|
||||
else
|
||||
let pos = stridx(res, "\n\n")
|
||||
let res = strpart(res, pos+2)
|
||||
endif
|
||||
endwhile
|
||||
endif
|
||||
let pos = stridx(res, "\r\n\r\n")
|
||||
if pos != -1
|
||||
let content = strpart(res, pos+4)
|
||||
else
|
||||
let pos = stridx(res, "\n\n")
|
||||
let content = strpart(res, pos+2)
|
||||
endif
|
||||
return {
|
||||
\ "header" : split(res[:pos-1], '\r\?\n'),
|
||||
\ "content" : content
|
||||
\}
|
||||
endfunction
|
||||
|
||||
function! webapi#http#post(url, ...)
|
||||
let postdata = a:0 > 0 ? a:000[0] : {}
|
||||
let headdata = a:0 > 1 ? a:000[1] : {}
|
||||
let method = a:0 > 2 ? a:000[2] : "POST"
|
||||
let follow = a:0 > 3 ? a:000[3] : 1
|
||||
let url = a:url
|
||||
if type(postdata) == 4
|
||||
let postdatastr = webapi#http#encodeURI(postdata)
|
||||
else
|
||||
let postdatastr = postdata
|
||||
endif
|
||||
let file = tempname()
|
||||
if executable('curl')
|
||||
let command = printf('curl %s -s -k -i -X %s', (follow ? '-L' : ''), len(method) ? method : 'POST')
|
||||
let quote = &shellxquote == '"' ? "'" : '"'
|
||||
for key in keys(headdata)
|
||||
if has('win32')
|
||||
let command .= " -H " . quote . key . ": " . substitute(headdata[key], '"', '"""', 'g') . quote
|
||||
else
|
||||
let command .= " -H " . quote . key . ": " . headdata[key] . quote
|
||||
endif
|
||||
endfor
|
||||
let command .= " ".quote.url.quote
|
||||
call writefile(split(postdatastr, "\n"), file, "b")
|
||||
let res = s:system(command . " --data-binary @" . quote.file.quote)
|
||||
elseif executable('wget')
|
||||
let command = printf('wget -O- --save-headers --server-response -q %s', follow ? '-L' : '')
|
||||
let headdata['X-HTTP-Method-Override'] = method
|
||||
let quote = &shellxquote == '"' ? "'" : '"'
|
||||
for key in keys(headdata)
|
||||
if has('win32')
|
||||
let command .= " --header=" . quote . key . ": " . substitute(headdata[key], '"', '"""', 'g') . quote
|
||||
else
|
||||
let command .= " --header=" . quote . key . ": " . headdata[key] . quote
|
||||
endif
|
||||
endfor
|
||||
let command .= " ".quote.url.quote
|
||||
call writefile(split(postdatastr, "\n"), file, "b")
|
||||
let res = s:system(command . " --post-data @" . quote.file.quote)
|
||||
else
|
||||
throw "require `curl` or `wget` command"
|
||||
endif
|
||||
call delete(file)
|
||||
if follow != 0
|
||||
while res =~ '^HTTP/1.\d 3' || res =~ '^HTTP/1\.\d 200 Connection established' || res =~ '^HTTP/1\.\d 100 Continue'
|
||||
let pos = stridx(res, "\r\n\r\n")
|
||||
if pos != -1
|
||||
let res = strpart(res, pos+4)
|
||||
else
|
||||
let pos = stridx(res, "\n\n")
|
||||
let res = strpart(res, pos+2)
|
||||
endif
|
||||
endwhile
|
||||
endif
|
||||
let pos = stridx(res, "\r\n\r\n")
|
||||
if pos != -1
|
||||
let content = strpart(res, pos+4)
|
||||
else
|
||||
let pos = stridx(res, "\n\n")
|
||||
let content = strpart(res, pos+2)
|
||||
endif
|
||||
return {
|
||||
\ "header" : split(res[:pos-1], '\r\?\n'),
|
||||
\ "content" : content
|
||||
\}
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
||||
135
vim/bundle/webapi-vim/autoload/webapi/json.vim
Normal file
135
vim/bundle/webapi-vim/autoload/webapi/json.vim
Normal file
@@ -0,0 +1,135 @@
|
||||
" json
|
||||
" Last Change: 2012-03-08
|
||||
" Maintainer: Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
" License: This file is placed in the public domain.
|
||||
" Reference:
|
||||
"
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! webapi#json#null()
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! webapi#json#true()
|
||||
return 1
|
||||
endfunction
|
||||
|
||||
function! webapi#json#false()
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! s:nr2byte(nr)
|
||||
if a:nr < 0x80
|
||||
return nr2char(a:nr)
|
||||
elseif a:nr < 0x800
|
||||
return nr2char(a:nr/64+192).nr2char(a:nr%64+128)
|
||||
else
|
||||
return nr2char(a:nr/4096%16+224).nr2char(a:nr/64%64+128).nr2char(a:nr%64+128)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:nr2enc_char(charcode)
|
||||
if &encoding == 'utf-8'
|
||||
return nr2char(a:charcode)
|
||||
endif
|
||||
let char = s:nr2byte(a:charcode)
|
||||
if strlen(char) > 1
|
||||
let char = strtrans(iconv(char, 'utf-8', &encoding))
|
||||
endif
|
||||
return char
|
||||
endfunction
|
||||
|
||||
function! s:fixup(val, tmp)
|
||||
if type(a:val) == 0
|
||||
return a:val
|
||||
elseif type(a:val) == 1
|
||||
if a:val == a:tmp.'null'
|
||||
return function('webapi#json#null')
|
||||
elseif a:val == a:tmp.'true'
|
||||
return function('webapi#json#true')
|
||||
elseif a:val == a:tmp.'false'
|
||||
return function('webapi#json#false')
|
||||
endif
|
||||
return a:val
|
||||
elseif type(a:val) == 2
|
||||
return a:val
|
||||
elseif type(a:val) == 3
|
||||
return map(a:val, 's:fixup(v:val, a:tmp)')
|
||||
elseif type(a:val) == 4
|
||||
return map(a:val, 's:fixup(v:val, a:tmp)')
|
||||
else
|
||||
return string(a:val)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! webapi#json#decode(json)
|
||||
let json = iconv(a:json, "utf-8", &encoding)
|
||||
if get(g:, 'webapi#json#parse_strict', 1) == 1 && substitute(substitute(substitute(
|
||||
\ json,
|
||||
\ '\\\%(["\\/bfnrt]\|u[0-9a-fA-F]\{4}\)', '\@', 'g'),
|
||||
\ '"[^\"\\\n\r]*\"\|true\|false\|null\|-\?\d\+'
|
||||
\ . '\%(\.\d*\)\?\%([eE][+\-]\{-}\d\+\)\?', ']', 'g'),
|
||||
\ '\%(^\|:\|,\)\%(\s*\[\)\+', '', 'g') !~ '^[\],:{} \t\n]*$'
|
||||
throw json
|
||||
endif
|
||||
let json = substitute(json, '\n', '', 'g')
|
||||
let json = substitute(json, '\\u34;', '\\"', 'g')
|
||||
if v:version >= 703 && has('patch780')
|
||||
let json = substitute(json, '\\u\(\x\x\x\x\)', '\=iconv(nr2char(str2nr(submatch(1), 16), 1), "utf-8", &encoding)', 'g')
|
||||
else
|
||||
let json = substitute(json, '\\u\(\x\x\x\x\)', '\=s:nr2enc_char("0x".submatch(1))', 'g')
|
||||
endif
|
||||
if get(g:, 'webapi#json#allow_nil', 0) != 0
|
||||
let tmp = '__WEBAPI_JSON__'
|
||||
while 1
|
||||
if stridx(json, tmp) == -1
|
||||
break
|
||||
endif
|
||||
let tmp .= '_'
|
||||
endwhile
|
||||
let [null,true,false] = [
|
||||
\ tmp.'null',
|
||||
\ tmp.'true',
|
||||
\ tmp.'false']
|
||||
sandbox let ret = eval(json)
|
||||
call s:fixup(ret, tmp)
|
||||
else
|
||||
let [null,true,false] = [0,1,0]
|
||||
sandbox let ret = eval(json)
|
||||
endif
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! webapi#json#encode(val)
|
||||
if type(a:val) == 0
|
||||
return a:val
|
||||
elseif type(a:val) == 1
|
||||
let json = '"' . escape(a:val, '\"') . '"'
|
||||
let json = substitute(json, "\r", '\\r', 'g')
|
||||
let json = substitute(json, "\n", '\\n', 'g')
|
||||
let json = substitute(json, "\t", '\\t', 'g')
|
||||
let json = substitute(json, '\([[:cntrl:]]\)', '\=printf("\x%02d", char2nr(submatch(1)))', 'g')
|
||||
return iconv(json, &encoding, "utf-8")
|
||||
elseif type(a:val) == 2
|
||||
let s = string(a:val)
|
||||
if s == "function('webapi#json#null')"
|
||||
return 'null'
|
||||
elseif s == "function('webapi#json#true')"
|
||||
return 'true'
|
||||
elseif s == "function('webapi#json#false')"
|
||||
return 'false'
|
||||
endif
|
||||
elseif type(a:val) == 3
|
||||
return '[' . join(map(copy(a:val), 'webapi#json#encode(v:val)'), ',') . ']'
|
||||
elseif type(a:val) == 4
|
||||
return '{' . join(map(keys(a:val), 'webapi#json#encode(v:val).":".webapi#json#encode(a:val[v:val])'), ',') . '}'
|
||||
else
|
||||
return string(a:val)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
||||
73
vim/bundle/webapi-vim/autoload/webapi/jsonrpc.vim
Normal file
73
vim/bundle/webapi-vim/autoload/webapi/jsonrpc.vim
Normal file
@@ -0,0 +1,73 @@
|
||||
" jsonrpc
|
||||
" Last Change: 2012-03-08
|
||||
" Maintainer: Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
" License: This file is placed in the public domain.
|
||||
" Reference:
|
||||
" http://tools.ietf.org/rfc/rfc4627.txt
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! webapi#jsonrpc#call(uri, func, args)
|
||||
let data = webapi#json#encode({
|
||||
\ 'jsonrpc': '2.0',
|
||||
\ 'method': a:func,
|
||||
\ 'params': a:args,
|
||||
\})
|
||||
let res = webapi#http#post(a:uri, data, {"Content-Type": "application/json"})
|
||||
let obj = webapi#json#decode(res.content)
|
||||
if has_key(obj, 'error')
|
||||
if type(obj.error) == 0 && obj.error != 0
|
||||
throw obj.error
|
||||
elseif type(obj.error) == 1 && obj.error != ''
|
||||
throw obj.error
|
||||
elseif type(obj.error) == 2 && string(obj.error) != "function('webapi#json#null')"
|
||||
throw obj.error
|
||||
endif
|
||||
endif
|
||||
if has_key(obj, 'result')
|
||||
return obj.result
|
||||
endif
|
||||
throw "Parse Error"
|
||||
endfunction
|
||||
|
||||
function! webapi#jsonrpc#wrap(contexts)
|
||||
let api = {}
|
||||
for context in a:contexts
|
||||
let target = api
|
||||
let namespaces = split(context.name, '\.')[:-2]
|
||||
if len(namespaces) > 0
|
||||
for ns in namespaces
|
||||
if !has_key(target, ns)
|
||||
let target[ns] = {".uri": context.uri}
|
||||
endif
|
||||
let target = target[ns]
|
||||
endfor
|
||||
endif
|
||||
if !has_key(context, 'argnames')
|
||||
let context['argnames'] = ['args']
|
||||
let arglist = 'a:args'
|
||||
else
|
||||
if len(context.argnames) && context.argnames[-1] == '...'
|
||||
let arglist = '[' . join(map(copy(context.argnames[:-2]),'"a:".v:val'),',') . ']+a:000'
|
||||
else
|
||||
let arglist = '[' . join(map(copy(context.argnames),'"a:".v:val'),',') . ']'
|
||||
endif
|
||||
endif
|
||||
if has_key(context, 'alias')
|
||||
exe "function api.".context.alias."(".join(context.argnames,",").") dict\n"
|
||||
\. " return webapi#jsonrpc#call(self['.uri'], '".context.name."', ".arglist.")\n"
|
||||
\. "endfunction\n"
|
||||
else
|
||||
exe "function api.".context.name."(".join(context.argnames,",").") dict\n"
|
||||
\. " return webapi#jsonrpc#call('".context.uri."', '".context.name."', ".arglist.")\n"
|
||||
\. "endfunction\n"
|
||||
endif
|
||||
endfor
|
||||
return api
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
||||
46
vim/bundle/webapi-vim/autoload/webapi/metaweblog.vim
Normal file
46
vim/bundle/webapi-vim/autoload/webapi/metaweblog.vim
Normal file
@@ -0,0 +1,46 @@
|
||||
" metaweblog
|
||||
" Last Change: 2010-09-10
|
||||
" Maintainer: Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
" License: This file is placed in the public domain.
|
||||
" Reference:
|
||||
" http://tools.ietf.org/rfc/rfc3529.txt
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:template = {"uri" : ""}
|
||||
|
||||
function! s:template.newPost(blogid, username, password, content, publish) dict
|
||||
return webapi#xmlrpc#call(self.uri, 'metaWeblog.newPost', [a:blogid, a:username, a:password, a:content, a:publish])
|
||||
endfunction
|
||||
|
||||
function! s:template.editPost(postid, username, password, content, publish) dict
|
||||
return webapi#xmlrpc#call(self.uri, 'metaWeblog.editPost', [a:postid, a:username, a:password, a:content, a:publish])
|
||||
endfunction
|
||||
|
||||
function! s:template.getPost(postid, username, password) dict
|
||||
return webapi#xmlrpc#call(self.uri, 'metaWeblog.getPost', [a:postid, a:username, a:password])
|
||||
endfunction
|
||||
|
||||
function! s:template.getRecentPosts(blogid, username, password, numberOfPosts) dict
|
||||
return webapi#xmlrpc#call(self.uri, 'metaWeblog.getRecentPosts', [a:blogid, a:username, a:password, a:numberOfPosts])
|
||||
endfunction
|
||||
|
||||
function! s:template.deletePost(appkey, postid, username, password, ...) dict
|
||||
return webapi#xmlrpc#call(self.uri, 'blogger.deletePost', [a:apikey, a:postid, a:username, a:password])
|
||||
endfunction
|
||||
|
||||
function! s:template.newMediaObject(blogid, username, password, file) dict
|
||||
return webapi#xmlrpc#call(self.uri, 'metaWeblog.newMediaObject', [a:blogid, a:username, a:password, a:file])
|
||||
endfunction
|
||||
|
||||
function! webapi#metaWeblog#proxy(uri)
|
||||
let ctx = deepcopy(s:template)
|
||||
let ctx.uri = a:uri
|
||||
return ctx
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
||||
162
vim/bundle/webapi-vim/autoload/webapi/oauth.vim
Normal file
162
vim/bundle/webapi-vim/autoload/webapi/oauth.vim
Normal file
@@ -0,0 +1,162 @@
|
||||
" oauth
|
||||
" Last Change: 2010-09-10
|
||||
" Maintainer: Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
" License: This file is placed in the public domain.
|
||||
" Reference:
|
||||
" http://tools.ietf.org/rfc/rfc5849.txt
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! webapi#oauth#request_token(url, ctx, ...)
|
||||
let params = a:0 > 0 ? a:000[0] : {}
|
||||
let query = {}
|
||||
let time_stamp = localtime()
|
||||
let nonce = time_stamp . " " . time_stamp
|
||||
let nonce = webapi#sha1#sha1(nonce)[0:28]
|
||||
let query["oauth_consumer_key"] = a:ctx.consumer_key
|
||||
let query["oauth_nonce"] = nonce
|
||||
let query["oauth_request_method"] = "POST"
|
||||
let query["oauth_signature_method"] = "HMAC-SHA1"
|
||||
let query["oauth_timestamp"] = time_stamp
|
||||
let query["oauth_version"] = "1.0"
|
||||
for key in keys(params)
|
||||
let query[key] = params[key]
|
||||
endfor
|
||||
let query_string = "POST&"
|
||||
let query_string .= webapi#http#encodeURI(a:url)
|
||||
let query_string .= "&"
|
||||
let query_string .= webapi#http#encodeURI(webapi#http#encodeURI(query))
|
||||
let hmacsha1 = webapi#hmac#sha1(webapi#http#encodeURI(a:ctx.consumer_secret) . "&", query_string)
|
||||
let query["oauth_signature"] = webapi#base64#b64encodebin(hmacsha1)
|
||||
let res = webapi#http#post(a:url, query, {})
|
||||
let a:ctx.request_token = webapi#http#decodeURI(substitute(filter(split(res.content, "&"), "v:val =~ '^oauth_token='")[0], '^[^=]*=', '', ''))
|
||||
let a:ctx.request_token_secret = webapi#http#decodeURI(substitute(filter(split(res.content, "&"), "v:val =~ '^oauth_token_secret='")[0], '^[^=]*=', '', ''))
|
||||
return a:ctx
|
||||
endfunction
|
||||
|
||||
function! webapi#oauth#access_token(url, ctx, ...)
|
||||
let params = a:0 > 0 ? a:000[0] : {}
|
||||
let query = {}
|
||||
let time_stamp = localtime()
|
||||
let nonce = time_stamp . " " . time_stamp
|
||||
let nonce = webapi#sha1#sha1(nonce)[0:28]
|
||||
let query["oauth_consumer_key"] = a:ctx.consumer_key
|
||||
let query["oauth_nonce"] = nonce
|
||||
let query["oauth_request_method"] = "POST"
|
||||
let query["oauth_signature_method"] = "HMAC-SHA1"
|
||||
let query["oauth_timestamp"] = time_stamp
|
||||
let query["oauth_token"] = a:ctx.request_token
|
||||
let query["oauth_token_secret"] = a:ctx.request_token_secret
|
||||
let query["oauth_version"] = "1.0"
|
||||
for key in keys(params)
|
||||
let query[key] = params[key]
|
||||
endfor
|
||||
let query_string = "POST&"
|
||||
let query_string .= webapi#http#encodeURI(a:url)
|
||||
let query_string .= "&"
|
||||
let query_string .= webapi#http#encodeURI(webapi#http#encodeURI(query))
|
||||
let hmacsha1 = webapi#hmac#sha1(webapi#http#encodeURI(a:ctx.consumer_secret) . "&" . webapi#http#encodeURI(a:ctx.request_token_secret), query_string)
|
||||
let query["oauth_signature"] = webapi#base64#b64encodebin(hmacsha1)
|
||||
let res = webapi#http#post(a:url, query, {})
|
||||
let a:ctx.access_token = webapi#http#decodeURI(substitute(filter(split(res.content, "&"), "v:val =~ '^oauth_token='")[0], '^[^=]*=', '', ''))
|
||||
let a:ctx.access_token_secret = webapi#http#decodeURI(substitute(filter(split(res.content, "&"), "v:val =~ '^oauth_token_secret='")[0], '^[^=]*=', '', ''))
|
||||
return a:ctx
|
||||
endfunction
|
||||
|
||||
function! webapi#oauth#get(url, ctx, ...)
|
||||
let params = a:0 > 0 ? a:000[0] : {}
|
||||
let getdata = a:0 > 1 ? a:000[1] : {}
|
||||
let headdata = a:0 > 2 ? a:000[2] : {}
|
||||
let query = {}
|
||||
let time_stamp = localtime()
|
||||
let nonce = time_stamp . " " . time_stamp
|
||||
let nonce = webapi#sha1#sha1(nonce)[0:28]
|
||||
let query["oauth_consumer_key"] = a:ctx.consumer_key
|
||||
let query["oauth_nonce"] = nonce
|
||||
let query["oauth_request_method"] = "GET"
|
||||
let query["oauth_signature_method"] = "HMAC-SHA1"
|
||||
let query["oauth_timestamp"] = time_stamp
|
||||
let query["oauth_token"] = a:ctx.access_token
|
||||
let query["oauth_version"] = "1.0"
|
||||
if type(params) == 4
|
||||
for key in keys(params)
|
||||
let query[key] = params[key]
|
||||
endfor
|
||||
endif
|
||||
if type(getdata) == 4
|
||||
for key in keys(getdata)
|
||||
let query[key] = getdata[key]
|
||||
endfor
|
||||
endif
|
||||
let query_string = query["oauth_request_method"] . "&"
|
||||
let query_string .= webapi#http#encodeURI(a:url)
|
||||
let query_string .= "&"
|
||||
let query_string .= webapi#http#encodeURI(webapi#http#encodeURI(query))
|
||||
let hmacsha1 = webapi#hmac#sha1(webapi#http#encodeURI(a:ctx.consumer_secret) . "&" . webapi#http#encodeURI(a:ctx.access_token_secret), query_string)
|
||||
let query["oauth_signature"] = webapi#base64#b64encodebin(hmacsha1)
|
||||
if type(getdata) == 4
|
||||
for key in keys(getdata)
|
||||
call remove(query, key)
|
||||
endfor
|
||||
endif
|
||||
let auth = 'OAuth '
|
||||
for key in sort(keys(query))
|
||||
let auth .= key . '="' . webapi#http#encodeURI(query[key]) . '", '
|
||||
endfor
|
||||
let auth = auth[:-3]
|
||||
let headdata["Authorization"] = auth
|
||||
let res = webapi#http#get(a:url, getdata, headdata)
|
||||
return res
|
||||
endfunction
|
||||
|
||||
function! webapi#oauth#post(url, ctx, ...)
|
||||
let params = a:0 > 0 ? a:000[0] : {}
|
||||
let postdata = a:0 > 1 ? a:000[1] : {}
|
||||
let headdata = a:0 > 2 ? a:000[2] : {}
|
||||
let query = {}
|
||||
let time_stamp = localtime()
|
||||
let nonce = time_stamp . " " . time_stamp
|
||||
let nonce = webapi#sha1#sha1(nonce)[0:28]
|
||||
let query["oauth_consumer_key"] = a:ctx.consumer_key
|
||||
let query["oauth_nonce"] = nonce
|
||||
let query["oauth_request_method"] = "POST"
|
||||
let query["oauth_signature_method"] = "HMAC-SHA1"
|
||||
let query["oauth_timestamp"] = time_stamp
|
||||
let query["oauth_token"] = a:ctx.access_token
|
||||
let query["oauth_version"] = "1.0"
|
||||
if type(params) == 4
|
||||
for key in keys(params)
|
||||
let query[key] = params[key]
|
||||
endfor
|
||||
endif
|
||||
if type(postdata) == 4
|
||||
for key in keys(postdata)
|
||||
let query[key] = postdata[key]
|
||||
endfor
|
||||
endif
|
||||
let query_string = query["oauth_request_method"] . "&"
|
||||
let query_string .= webapi#http#encodeURI(a:url)
|
||||
let query_string .= "&"
|
||||
let query_string .= webapi#http#encodeURI(webapi#http#encodeURI(query))
|
||||
let hmacsha1 = webapi#hmac#sha1(webapi#http#encodeURI(a:ctx.consumer_secret) . "&" . webapi#http#encodeURI(a:ctx.access_token_secret), query_string)
|
||||
let query["oauth_signature"] = webapi#base64#b64encodebin(hmacsha1)
|
||||
if type(postdata) == 4
|
||||
for key in keys(postdata)
|
||||
call remove(query, key)
|
||||
endfor
|
||||
endif
|
||||
let auth = 'OAuth '
|
||||
for key in sort(keys(query))
|
||||
let auth .= webapi#http#escape(key) . '="' . webapi#http#escape(query[key]) . '",'
|
||||
endfor
|
||||
let auth = auth[:-2]
|
||||
let headdata["Authorization"] = auth
|
||||
let res = webapi#http#post(a:url, postdata, headdata)
|
||||
return res
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
||||
746
vim/bundle/webapi-vim/autoload/webapi/sha1.vim
Normal file
746
vim/bundle/webapi-vim/autoload/webapi/sha1.vim
Normal file
@@ -0,0 +1,746 @@
|
||||
" sha1 digest calculator
|
||||
" This is a port of rfc3174 sha1 function.
|
||||
" http://www.ietf.org/rfc/rfc3174.txt
|
||||
" Last Change: 2010-02-13
|
||||
" Maintainer: Yukihiro Nakadaira <yukihiro.nakadaira@gmail.com>
|
||||
" Original Copyright:
|
||||
" Copyright (C) The Internet Society (2001). All Rights Reserved.
|
||||
"
|
||||
" This document and translations of it may be copied and furnished to
|
||||
" others, and derivative works that comment on or otherwise explain it
|
||||
" or assist in its implementation may be prepared, copied, published
|
||||
" and distributed, in whole or in part, without restriction of any
|
||||
" kind, provided that the above copyright notice and this paragraph are
|
||||
" included on all such copies and derivative works. However, this
|
||||
" document itself may not be modified in any way, such as by removing
|
||||
" the copyright notice or references to the Internet Society or other
|
||||
" Internet organizations, except as needed for the purpose of
|
||||
" developing Internet standards in which case the procedures for
|
||||
" copyrights defined in the Internet Standards process must be
|
||||
" followed, or as required to translate it into languages other than
|
||||
" English.
|
||||
"
|
||||
" The limited permissions granted above are perpetual and will not be
|
||||
" revoked by the Internet Society or its successors or assigns.
|
||||
"
|
||||
" This document and the information contained herein is provided on an
|
||||
" "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
|
||||
" TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
|
||||
" BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
|
||||
" HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
|
||||
" MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! webapi#sha1#sha1(str)
|
||||
return s:SHA1Digest(s:str2bytes(a:str))
|
||||
endfunction
|
||||
|
||||
function! webapi#sha1#sha1bin(bin)
|
||||
return s:SHA1Digest(a:bin)
|
||||
endfunction
|
||||
|
||||
function! webapi#sha1#test()
|
||||
call s:main()
|
||||
endfunction
|
||||
|
||||
function! s:SHA1Digest(bytes)
|
||||
let sha = deepcopy(s:SHA1Context, 1)
|
||||
let Message_Digest = repeat([0], 20)
|
||||
|
||||
let err = s:SHA1Reset(sha)
|
||||
if err
|
||||
throw printf("SHA1Reset Error %d", err)
|
||||
endif
|
||||
|
||||
let err = s:SHA1Input(sha, a:bytes)
|
||||
if err
|
||||
throw printf("SHA1Input Error %d", err)
|
||||
endif
|
||||
|
||||
let err = s:SHA1Result(sha, Message_Digest)
|
||||
if err
|
||||
throw printf("SHA1Result Error %d", err)
|
||||
endif
|
||||
|
||||
return join(map(Message_Digest, 'printf("%02x", v:val)'), '')
|
||||
endfunction
|
||||
|
||||
"
|
||||
" sha1.h
|
||||
"
|
||||
" Description:
|
||||
" This is the header file for code which implements the Secure
|
||||
" Hashing Algorithm 1 as defined in FIPS PUB 180-1 published
|
||||
" April 17, 1995.
|
||||
"
|
||||
" Many of the variable names in this code, especially the
|
||||
" single character names, were used because those were the names
|
||||
" used in the publication.
|
||||
"
|
||||
" Please read the file sha1.c for more information.
|
||||
|
||||
"
|
||||
" If you do not have the ISO standard stdint.h header file, then you
|
||||
" must typdef the following:
|
||||
" name meaning
|
||||
" uint32_t unsigned 32 bit integer
|
||||
" uint8_t unsigned 8 bit integer (i.e., unsigned char)
|
||||
" int_least16_t integer of >= 16 bits
|
||||
"
|
||||
"
|
||||
|
||||
" enum
|
||||
let s:shaSuccess = 0
|
||||
let s:shaNull = 1 " Null pointer parameter
|
||||
let s:shaInputTooLong = 2 " input data too long
|
||||
let s:shaStateError = 3 " called Input after Result
|
||||
|
||||
" define
|
||||
let s:SHA1HashSize = 20
|
||||
|
||||
"
|
||||
" This structure will hold context information for the SHA-1
|
||||
" hashing operation
|
||||
"
|
||||
" struct
|
||||
let s:SHA1Context = {}
|
||||
" uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */
|
||||
let s:SHA1Context.Intermediate_Hash = repeat([0], s:SHA1HashSize / 4)
|
||||
" uint32_t Length_Low; /* Message length in bits */
|
||||
let s:SHA1Context.Length_Low = 0
|
||||
" uint32_t Length_High; /* Message length in bits */
|
||||
let s:SHA1Context.Length_High = 0
|
||||
" /* Index into message block array */
|
||||
" int_least16_t Message_Block_Index;
|
||||
let s:SHA1Context.Message_Block_Index = 0
|
||||
" uint8_t Message_Block[64]; /* 512-bit message blocks */
|
||||
let s:SHA1Context.Message_Block = repeat([0], 64)
|
||||
" int Computed; /* Is the digest computed? */
|
||||
let s:SHA1Context.Computed = 0
|
||||
" int Corrupted; /* Is the message digest corrupted? */
|
||||
let s:SHA1Context.Corrupted = 0
|
||||
|
||||
"
|
||||
" sha1.c
|
||||
"
|
||||
" Description:
|
||||
" This file implements the Secure Hashing Algorithm 1 as
|
||||
" defined in FIPS PUB 180-1 published April 17, 1995.
|
||||
"
|
||||
" The SHA-1, produces a 160-bit message digest for a given
|
||||
" data stream. It should take about 2**n steps to find a
|
||||
" message with the same digest as a given message and
|
||||
" 2**(n/2) to find any two messages with the same digest,
|
||||
" when n is the digest size in bits. Therefore, this
|
||||
" algorithm can serve as a means of providing a
|
||||
" "fingerprint" for a message.
|
||||
"
|
||||
" Portability Issues:
|
||||
" SHA-1 is defined in terms of 32-bit "words". This code
|
||||
" uses <stdint.h> (included via "sha1.h" to define 32 and 8
|
||||
" bit unsigned integer types. If your C compiler does not
|
||||
" support 32 bit unsigned integers, this code is not
|
||||
" appropriate.
|
||||
"
|
||||
" Caveats:
|
||||
" SHA-1 is designed to work with messages less than 2^64 bits
|
||||
" long. Although SHA-1 allows a message digest to be generated
|
||||
" for messages of any number of bits less than 2^64, this
|
||||
" implementation only works with messages with a length that is
|
||||
" a multiple of the size of an 8-bit character.
|
||||
"
|
||||
"
|
||||
|
||||
"
|
||||
" Define the SHA1 circular left shift macro
|
||||
"
|
||||
"#define SHA1CircularShift(bits,word) \
|
||||
" (((word) << (bits)) | ((word) >> (32-(bits))))
|
||||
function s:SHA1CircularShift(bits, word)
|
||||
return s:bitwise_or(s:bitwise_lshift(a:word, a:bits), s:bitwise_rshift(a:word, 32 - a:bits))
|
||||
endfunction
|
||||
|
||||
"
|
||||
" SHA1Reset
|
||||
"
|
||||
" Description:
|
||||
" This function will initialize the SHA1Context in preparation
|
||||
" for computing a new SHA1 message digest.
|
||||
"
|
||||
" Parameters:
|
||||
" context: [in/out]
|
||||
" The context to reset.
|
||||
"
|
||||
" Returns:
|
||||
" sha Error Code.
|
||||
"
|
||||
"
|
||||
" int SHA1Reset(SHA1Context *context)
|
||||
function s:SHA1Reset(context)
|
||||
if empty(a:context)
|
||||
return s:shaNull
|
||||
endif
|
||||
|
||||
let a:context.Length_Low = 0
|
||||
let a:context.Length_High = 0
|
||||
let a:context.Message_Block_Index = 0
|
||||
|
||||
let a:context.Intermediate_Hash[0] = 0x67452301
|
||||
let a:context.Intermediate_Hash[1] = 0xEFCDAB89
|
||||
let a:context.Intermediate_Hash[2] = 0x98BADCFE
|
||||
let a:context.Intermediate_Hash[3] = 0x10325476
|
||||
let a:context.Intermediate_Hash[4] = 0xC3D2E1F0
|
||||
|
||||
let a:context.Computed = 0
|
||||
let a:context.Corrupted = 0
|
||||
|
||||
return s:shaSuccess
|
||||
endfunction
|
||||
|
||||
"
|
||||
" SHA1Result
|
||||
"
|
||||
" Description:
|
||||
" This function will return the 160-bit message digest into the
|
||||
" Message_Digest array provided by the caller.
|
||||
" NOTE: The first octet of hash is stored in the 0th element,
|
||||
" the last octet of hash in the 19th element.
|
||||
"
|
||||
" Parameters:
|
||||
" context: [in/out]
|
||||
" The context to use to calculate the SHA-1 hash.
|
||||
" Message_Digest: [out]
|
||||
" Where the digest is returned.
|
||||
"
|
||||
" Returns:
|
||||
" sha Error Code.
|
||||
"
|
||||
"
|
||||
"int SHA1Result( SHA1Context *context,
|
||||
" uint8_t Message_Digest[SHA1HashSize])
|
||||
function s:SHA1Result(context, Message_Digest)
|
||||
if empty(a:context) || empty(a:Message_Digest)
|
||||
return s:shaNull
|
||||
endif
|
||||
|
||||
if a:context.Corrupted
|
||||
return a:context.Corrupted
|
||||
endif
|
||||
|
||||
if !a:context.Computed
|
||||
call s:SHA1PadMessage(a:context)
|
||||
for i in range(64)
|
||||
" message may be sensitive, clear it out
|
||||
let a:context.Message_Block[i] = 0
|
||||
endfor
|
||||
let a:context.Length_Low = 0 " and clear length
|
||||
let a:context.Length_High = 0
|
||||
let a:context.Computed = 1
|
||||
endif
|
||||
|
||||
for i in range(s:SHA1HashSize)
|
||||
let a:Message_Digest[i] = s:uint8(
|
||||
\ s:bitwise_rshift(
|
||||
\ a:context.Intermediate_Hash[s:bitwise_rshift(i, 2)],
|
||||
\ 8 * (3 - s:bitwise_and(i, 0x03))
|
||||
\ )
|
||||
\ )
|
||||
endfor
|
||||
|
||||
return s:shaSuccess
|
||||
endfunction
|
||||
|
||||
"
|
||||
" SHA1Input
|
||||
"
|
||||
" Description:
|
||||
" This function accepts an array of octets as the next portion
|
||||
" of the message.
|
||||
"
|
||||
" Parameters:
|
||||
" context: [in/out]
|
||||
" The SHA context to update
|
||||
" message_array: [in]
|
||||
" An array of characters representing the next portion of
|
||||
" the message.
|
||||
" length: [in]
|
||||
" The length of the message in message_array
|
||||
"
|
||||
" Returns:
|
||||
" sha Error Code.
|
||||
"
|
||||
"
|
||||
"int SHA1Input( SHA1Context *context,
|
||||
" const uint8_t *message_array,
|
||||
" unsigned length)
|
||||
function s:SHA1Input(context, message_array)
|
||||
if !len(a:message_array)
|
||||
return s:shaSuccess
|
||||
endif
|
||||
|
||||
if empty(a:context) || empty(a:message_array)
|
||||
return s:shaNull
|
||||
endif
|
||||
|
||||
if a:context.Computed
|
||||
let a:context.Corrupted = s:shaStateError
|
||||
return s:shaStateError
|
||||
endif
|
||||
|
||||
if a:context.Corrupted
|
||||
return a:context.Corrupted
|
||||
endif
|
||||
|
||||
for x in a:message_array
|
||||
if a:context.Corrupted
|
||||
break
|
||||
endif
|
||||
let a:context.Message_Block[a:context.Message_Block_Index] = s:bitwise_and(x, 0xFF)
|
||||
let a:context.Message_Block_Index += 1
|
||||
|
||||
let a:context.Length_Low += 8
|
||||
if a:context.Length_Low == 0
|
||||
let a:context.Length_High += 1
|
||||
if a:context.Length_High == 0
|
||||
" Message is too long
|
||||
let a:context.Corrupted = 1
|
||||
endif
|
||||
endif
|
||||
|
||||
if a:context.Message_Block_Index == 64
|
||||
call s:SHA1ProcessMessageBlock(a:context)
|
||||
endif
|
||||
endfor
|
||||
|
||||
return s:shaSuccess
|
||||
endfunction
|
||||
|
||||
"
|
||||
" SHA1ProcessMessageBlock
|
||||
"
|
||||
" Description:
|
||||
" This function will process the next 512 bits of the message
|
||||
" stored in the Message_Block array.
|
||||
"
|
||||
" Parameters:
|
||||
" None.
|
||||
"
|
||||
" Returns:
|
||||
" Nothing.
|
||||
"
|
||||
" Comments:
|
||||
" Many of the variable names in this code, especially the
|
||||
" single character names, were used because those were the
|
||||
" names used in the publication.
|
||||
"
|
||||
"
|
||||
"
|
||||
" void SHA1ProcessMessageBlock(SHA1Context *context)
|
||||
function s:SHA1ProcessMessageBlock(context)
|
||||
" Constants defined in SHA-1
|
||||
let K = [
|
||||
\ 0x5A827999,
|
||||
\ 0x6ED9EBA1,
|
||||
\ 0x8F1BBCDC,
|
||||
\ 0xCA62C1D6
|
||||
\ ]
|
||||
let t = 0 " Loop counter
|
||||
let temp = 0 " Temporary word value
|
||||
let W = repeat([0], 80) " Word sequence
|
||||
let [A, B, C, D, E] = [0, 0, 0, 0, 0] " Word buffers
|
||||
|
||||
"
|
||||
" Initialize the first 16 words in the array W
|
||||
"
|
||||
for t in range(16)
|
||||
let W[t] = s:bitwise_lshift(a:context.Message_Block[t * 4], 24)
|
||||
let W[t] = s:bitwise_or(W[t], s:bitwise_lshift(a:context.Message_Block[t * 4 + 1], 16))
|
||||
let W[t] = s:bitwise_or(W[t], s:bitwise_lshift(a:context.Message_Block[t * 4 + 2], 8))
|
||||
let W[t] = s:bitwise_or(W[t], a:context.Message_Block[t * 4 + 3])
|
||||
endfor
|
||||
|
||||
for t in range(16, 79)
|
||||
let W[t] = s:SHA1CircularShift(1, s:bitwise_xor(s:bitwise_xor(s:bitwise_xor(W[t-3], W[t-8]), W[t-14]), W[t-16]))
|
||||
endfor
|
||||
|
||||
let A = a:context.Intermediate_Hash[0]
|
||||
let B = a:context.Intermediate_Hash[1]
|
||||
let C = a:context.Intermediate_Hash[2]
|
||||
let D = a:context.Intermediate_Hash[3]
|
||||
let E = a:context.Intermediate_Hash[4]
|
||||
|
||||
for t in range(20)
|
||||
let temp = s:SHA1CircularShift(5,A) +
|
||||
\ s:bitwise_or(s:bitwise_and(B, C), s:bitwise_and(s:bitwise_not(B), D)) +
|
||||
\ E + W[t] + K[0]
|
||||
let E = D
|
||||
let D = C
|
||||
let C = s:SHA1CircularShift(30,B)
|
||||
let B = A
|
||||
let A = temp
|
||||
endfor
|
||||
|
||||
for t in range(20, 39)
|
||||
let temp = s:SHA1CircularShift(5,A) + s:bitwise_xor(s:bitwise_xor(B, C), D) + E + W[t] + K[1]
|
||||
let E = D
|
||||
let D = C
|
||||
let C = s:SHA1CircularShift(30,B)
|
||||
let B = A
|
||||
let A = temp
|
||||
endfor
|
||||
|
||||
for t in range(40, 59)
|
||||
let temp = s:SHA1CircularShift(5,A) +
|
||||
\ s:bitwise_or(s:bitwise_or(s:bitwise_and(B, C), s:bitwise_and(B, D)), s:bitwise_and(C, D)) +
|
||||
\ E + W[t] + K[2]
|
||||
let E = D
|
||||
let D = C
|
||||
let C = s:SHA1CircularShift(30,B)
|
||||
let B = A
|
||||
let A = temp
|
||||
endfor
|
||||
|
||||
for t in range(60, 79)
|
||||
let temp = s:SHA1CircularShift(5,A) +
|
||||
\ s:bitwise_xor(s:bitwise_xor(B, C), D) + E + W[t] + K[3]
|
||||
let E = D
|
||||
let D = C
|
||||
let C = s:SHA1CircularShift(30,B)
|
||||
let B = A
|
||||
let A = temp
|
||||
endfor
|
||||
|
||||
let a:context.Intermediate_Hash[0] += A
|
||||
let a:context.Intermediate_Hash[1] += B
|
||||
let a:context.Intermediate_Hash[2] += C
|
||||
let a:context.Intermediate_Hash[3] += D
|
||||
let a:context.Intermediate_Hash[4] += E
|
||||
|
||||
let a:context.Message_Block_Index = 0
|
||||
endfunction
|
||||
|
||||
|
||||
"
|
||||
" SHA1PadMessage
|
||||
"
|
||||
" Description:
|
||||
" According to the standard, the message must be padded to an even
|
||||
" 512 bits. The first padding bit must be a '1'. The last 64
|
||||
" bits represent the length of the original message. All bits in
|
||||
" between should be 0. This function will pad the message
|
||||
" according to those rules by filling the Message_Block array
|
||||
" accordingly. It will also call the ProcessMessageBlock function
|
||||
" provided appropriately. When it returns, it can be assumed that
|
||||
" the message digest has been computed.
|
||||
"
|
||||
" Parameters:
|
||||
" context: [in/out]
|
||||
" The context to pad
|
||||
" ProcessMessageBlock: [in]
|
||||
" The appropriate SHA*ProcessMessageBlock function
|
||||
" Returns:
|
||||
" Nothing.
|
||||
"
|
||||
"
|
||||
" void SHA1PadMessage(SHA1Context *context)
|
||||
function s:SHA1PadMessage(context)
|
||||
"
|
||||
" Check to see if the current message block is too small to hold
|
||||
" the initial padding bits and length. If so, we will pad the
|
||||
" block, process it, and then continue padding into a second
|
||||
" block.
|
||||
"
|
||||
if a:context.Message_Block_Index > 55
|
||||
let a:context.Message_Block[a:context.Message_Block_Index] = 0x80
|
||||
let a:context.Message_Block_Index += 1
|
||||
while a:context.Message_Block_Index < 64
|
||||
let a:context.Message_Block[a:context.Message_Block_Index] = 0
|
||||
let a:context.Message_Block_Index += 1
|
||||
endwhile
|
||||
|
||||
call s:SHA1ProcessMessageBlock(a:context)
|
||||
|
||||
while a:context.Message_Block_Index < 56
|
||||
let a:context.Message_Block[a:context.Message_Block_Index] = 0
|
||||
let a:context.Message_Block_Index += 1
|
||||
endwhile
|
||||
else
|
||||
let a:context.Message_Block[a:context.Message_Block_Index] = 0x80
|
||||
let a:context.Message_Block_Index += 1
|
||||
while a:context.Message_Block_Index < 56
|
||||
let a:context.Message_Block[a:context.Message_Block_Index] = 0
|
||||
let a:context.Message_Block_Index += 1
|
||||
endwhile
|
||||
endif
|
||||
|
||||
"
|
||||
" Store the message length as the last 8 octets
|
||||
"
|
||||
let a:context.Message_Block[56] = s:uint8(s:bitwise_rshift(a:context.Length_High, 24))
|
||||
let a:context.Message_Block[57] = s:uint8(s:bitwise_rshift(a:context.Length_High, 16))
|
||||
let a:context.Message_Block[58] = s:uint8(s:bitwise_rshift(a:context.Length_High, 8))
|
||||
let a:context.Message_Block[59] = s:uint8(a:context.Length_High)
|
||||
let a:context.Message_Block[60] = s:uint8(s:bitwise_rshift(a:context.Length_Low, 24))
|
||||
let a:context.Message_Block[61] = s:uint8(s:bitwise_rshift(a:context.Length_Low, 16))
|
||||
let a:context.Message_Block[62] = s:uint8(s:bitwise_rshift(a:context.Length_Low, 8))
|
||||
let a:context.Message_Block[63] = s:uint8(a:context.Length_Low)
|
||||
|
||||
call s:SHA1ProcessMessageBlock(a:context)
|
||||
endfunction
|
||||
|
||||
"
|
||||
" sha1test.c
|
||||
"
|
||||
" Description:
|
||||
" This file will exercise the SHA-1 code performing the three
|
||||
" tests documented in FIPS PUB 180-1 plus one which calls
|
||||
" SHA1Input with an exact multiple of 512 bits, plus a few
|
||||
" error test checks.
|
||||
"
|
||||
" Portability Issues:
|
||||
" None.
|
||||
"
|
||||
"
|
||||
|
||||
"
|
||||
" Define patterns for testing
|
||||
"
|
||||
let s:TEST1 = "abc"
|
||||
let s:TEST2a = "abcdbcdecdefdefgefghfghighijhi"
|
||||
let s:TEST2b = "jkijkljklmklmnlmnomnopnopq"
|
||||
let s:TEST2 = s:TEST2a . s:TEST2b
|
||||
let s:TEST3 = "a"
|
||||
let s:TEST4a = "01234567012345670123456701234567"
|
||||
let s:TEST4b = "01234567012345670123456701234567"
|
||||
" an exact multiple of 512 bits
|
||||
let s:TEST4 = s:TEST4a . s:TEST4b
|
||||
let s:testarray = [
|
||||
\ s:TEST1,
|
||||
\ s:TEST2,
|
||||
\ s:TEST3,
|
||||
\ s:TEST4
|
||||
\ ]
|
||||
let s:repeatcount = [1, 1, 1000000, 10]
|
||||
let s:resultarray = [
|
||||
\ "A9 99 3E 36 47 06 81 6A BA 3E 25 71 78 50 C2 6C 9C D0 D8 9D",
|
||||
\ "84 98 3E 44 1C 3B D2 6E BA AE 4A A1 F9 51 29 E5 E5 46 70 F1",
|
||||
\ "34 AA 97 3C D4 C4 DA A4 F6 1E EB 2B DB AD 27 31 65 34 01 6F",
|
||||
\ "DE A3 56 A2 CD DD 90 C7 A7 EC ED C5 EB B5 63 93 4F 46 04 52"
|
||||
\ ]
|
||||
|
||||
function s:main()
|
||||
let sha = deepcopy(s:SHA1Context, 1)
|
||||
let Message_Digest = repeat([0], 20)
|
||||
|
||||
"
|
||||
" Perform SHA-1 tests
|
||||
"
|
||||
for j in range(len(s:testarray))
|
||||
if j == 2
|
||||
echo "Test 3 will take about 1 hour. Press CTRL-C to skip."
|
||||
endif
|
||||
echo ""
|
||||
echo printf("Test %d: %d, '%s'",
|
||||
\ j+1,
|
||||
\ s:repeatcount[j],
|
||||
\ s:testarray[j])
|
||||
|
||||
let err = s:SHA1Reset(sha)
|
||||
if err
|
||||
echo printf("SHA1Reset Error %d.", err )
|
||||
break " out of for j loop
|
||||
endif
|
||||
|
||||
try
|
||||
for i in range(s:repeatcount[j])
|
||||
let err = s:SHA1Input(sha, s:str2bytes(s:testarray[j]))
|
||||
if err
|
||||
echo printf("SHA1Input Error %d.", err )
|
||||
break " out of for i loop */
|
||||
endif
|
||||
endfor
|
||||
catch /^Vim:Interrupt$/
|
||||
echo "Skip ..."
|
||||
while getchar(0) | endwhile
|
||||
continue
|
||||
endtry
|
||||
|
||||
let err = s:SHA1Result(sha, Message_Digest)
|
||||
if err
|
||||
echo printf("SHA1Result Error %d, could not compute message digest.", err)
|
||||
else
|
||||
echo "\t"
|
||||
for i in range(20)
|
||||
echon printf("%02X ", Message_Digest[i])
|
||||
endfor
|
||||
echo ""
|
||||
endif
|
||||
echo "Should match:"
|
||||
echo printf("\t%s", s:resultarray[j])
|
||||
endfor
|
||||
|
||||
" Test some error returns
|
||||
let err = s:SHA1Input(sha, s:str2bytes(s:testarray[1][0:0]))
|
||||
echo printf("\nError %d. Should be %d.", err, s:shaStateError)
|
||||
let err = s:SHA1Reset(0)
|
||||
echo printf("\nError %d. Should be %d.", err, s:shaNull)
|
||||
endfunction
|
||||
|
||||
|
||||
|
||||
"---------------------------------------------------------------------
|
||||
" misc
|
||||
function! s:str2bytes(str)
|
||||
return map(range(len(a:str)), 'char2nr(a:str[v:val])')
|
||||
endfunction
|
||||
|
||||
function! s:cmp(a, b)
|
||||
let a = printf("%08x", a:a)
|
||||
let b = printf("%08x", a:b)
|
||||
return a < b ? -1 : a > b ? 1 : 0
|
||||
endfunction
|
||||
|
||||
function! s:uint8(n)
|
||||
return s:bitwise_and(a:n, 0xFF)
|
||||
endfunction
|
||||
|
||||
let s:k = [
|
||||
\ 0x1, 0x2, 0x4, 0x8,
|
||||
\ 0x10, 0x20, 0x40, 0x80,
|
||||
\ 0x100, 0x200, 0x400, 0x800,
|
||||
\ 0x1000, 0x2000, 0x4000, 0x8000,
|
||||
\ 0x10000, 0x20000, 0x40000, 0x80000,
|
||||
\ 0x100000, 0x200000, 0x400000, 0x800000,
|
||||
\ 0x1000000, 0x2000000, 0x4000000, 0x8000000,
|
||||
\ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
|
||||
\ ]
|
||||
|
||||
let s:and = [
|
||||
\ [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0],
|
||||
\ [0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1],
|
||||
\ [0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x2, 0x2],
|
||||
\ [0x0, 0x1, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3],
|
||||
\ [0x0, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x0, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4],
|
||||
\ [0x0, 0x1, 0x0, 0x1, 0x4, 0x5, 0x4, 0x5, 0x0, 0x1, 0x0, 0x1, 0x4, 0x5, 0x4, 0x5],
|
||||
\ [0x0, 0x0, 0x2, 0x2, 0x4, 0x4, 0x6, 0x6, 0x0, 0x0, 0x2, 0x2, 0x4, 0x4, 0x6, 0x6],
|
||||
\ [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7],
|
||||
\ [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8],
|
||||
\ [0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x8, 0x9, 0x8, 0x9, 0x8, 0x9, 0x8, 0x9],
|
||||
\ [0x0, 0x0, 0x2, 0x2, 0x0, 0x0, 0x2, 0x2, 0x8, 0x8, 0xA, 0xA, 0x8, 0x8, 0xA, 0xA],
|
||||
\ [0x0, 0x1, 0x2, 0x3, 0x0, 0x1, 0x2, 0x3, 0x8, 0x9, 0xA, 0xB, 0x8, 0x9, 0xA, 0xB],
|
||||
\ [0x0, 0x0, 0x0, 0x0, 0x4, 0x4, 0x4, 0x4, 0x8, 0x8, 0x8, 0x8, 0xC, 0xC, 0xC, 0xC],
|
||||
\ [0x0, 0x1, 0x0, 0x1, 0x4, 0x5, 0x4, 0x5, 0x8, 0x9, 0x8, 0x9, 0xC, 0xD, 0xC, 0xD],
|
||||
\ [0x0, 0x0, 0x2, 0x2, 0x4, 0x4, 0x6, 0x6, 0x8, 0x8, 0xA, 0xA, 0xC, 0xC, 0xE, 0xE],
|
||||
\ [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF]
|
||||
\ ]
|
||||
|
||||
let s:or = [
|
||||
\ [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF],
|
||||
\ [0x1, 0x1, 0x3, 0x3, 0x5, 0x5, 0x7, 0x7, 0x9, 0x9, 0xB, 0xB, 0xD, 0xD, 0xF, 0xF],
|
||||
\ [0x2, 0x3, 0x2, 0x3, 0x6, 0x7, 0x6, 0x7, 0xA, 0xB, 0xA, 0xB, 0xE, 0xF, 0xE, 0xF],
|
||||
\ [0x3, 0x3, 0x3, 0x3, 0x7, 0x7, 0x7, 0x7, 0xB, 0xB, 0xB, 0xB, 0xF, 0xF, 0xF, 0xF],
|
||||
\ [0x4, 0x5, 0x6, 0x7, 0x4, 0x5, 0x6, 0x7, 0xC, 0xD, 0xE, 0xF, 0xC, 0xD, 0xE, 0xF],
|
||||
\ [0x5, 0x5, 0x7, 0x7, 0x5, 0x5, 0x7, 0x7, 0xD, 0xD, 0xF, 0xF, 0xD, 0xD, 0xF, 0xF],
|
||||
\ [0x6, 0x7, 0x6, 0x7, 0x6, 0x7, 0x6, 0x7, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF],
|
||||
\ [0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF],
|
||||
\ [0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF],
|
||||
\ [0x9, 0x9, 0xB, 0xB, 0xD, 0xD, 0xF, 0xF, 0x9, 0x9, 0xB, 0xB, 0xD, 0xD, 0xF, 0xF],
|
||||
\ [0xA, 0xB, 0xA, 0xB, 0xE, 0xF, 0xE, 0xF, 0xA, 0xB, 0xA, 0xB, 0xE, 0xF, 0xE, 0xF],
|
||||
\ [0xB, 0xB, 0xB, 0xB, 0xF, 0xF, 0xF, 0xF, 0xB, 0xB, 0xB, 0xB, 0xF, 0xF, 0xF, 0xF],
|
||||
\ [0xC, 0xD, 0xE, 0xF, 0xC, 0xD, 0xE, 0xF, 0xC, 0xD, 0xE, 0xF, 0xC, 0xD, 0xE, 0xF],
|
||||
\ [0xD, 0xD, 0xF, 0xF, 0xD, 0xD, 0xF, 0xF, 0xD, 0xD, 0xF, 0xF, 0xD, 0xD, 0xF, 0xF],
|
||||
\ [0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF, 0xE, 0xF],
|
||||
\ [0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF]
|
||||
\ ]
|
||||
|
||||
let s:xor = [
|
||||
\ [0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF],
|
||||
\ [0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6, 0x9, 0x8, 0xB, 0xA, 0xD, 0xC, 0xF, 0xE],
|
||||
\ [0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5, 0xA, 0xB, 0x8, 0x9, 0xE, 0xF, 0xC, 0xD],
|
||||
\ [0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4, 0xB, 0xA, 0x9, 0x8, 0xF, 0xE, 0xD, 0xC],
|
||||
\ [0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3, 0xC, 0xD, 0xE, 0xF, 0x8, 0x9, 0xA, 0xB],
|
||||
\ [0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2, 0xD, 0xC, 0xF, 0xE, 0x9, 0x8, 0xB, 0xA],
|
||||
\ [0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1, 0xE, 0xF, 0xC, 0xD, 0xA, 0xB, 0x8, 0x9],
|
||||
\ [0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xF, 0xE, 0xD, 0xC, 0xB, 0xA, 0x9, 0x8],
|
||||
\ [0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7],
|
||||
\ [0x9, 0x8, 0xB, 0xA, 0xD, 0xC, 0xF, 0xE, 0x1, 0x0, 0x3, 0x2, 0x5, 0x4, 0x7, 0x6],
|
||||
\ [0xA, 0xB, 0x8, 0x9, 0xE, 0xF, 0xC, 0xD, 0x2, 0x3, 0x0, 0x1, 0x6, 0x7, 0x4, 0x5],
|
||||
\ [0xB, 0xA, 0x9, 0x8, 0xF, 0xE, 0xD, 0xC, 0x3, 0x2, 0x1, 0x0, 0x7, 0x6, 0x5, 0x4],
|
||||
\ [0xC, 0xD, 0xE, 0xF, 0x8, 0x9, 0xA, 0xB, 0x4, 0x5, 0x6, 0x7, 0x0, 0x1, 0x2, 0x3],
|
||||
\ [0xD, 0xC, 0xF, 0xE, 0x9, 0x8, 0xB, 0xA, 0x5, 0x4, 0x7, 0x6, 0x1, 0x0, 0x3, 0x2],
|
||||
\ [0xE, 0xF, 0xC, 0xD, 0xA, 0xB, 0x8, 0x9, 0x6, 0x7, 0x4, 0x5, 0x2, 0x3, 0x0, 0x1],
|
||||
\ [0xF, 0xE, 0xD, 0xC, 0xB, 0xA, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0]
|
||||
\ ]
|
||||
|
||||
function! s:bitwise_lshift(a, n)
|
||||
return a:a * s:k[a:n]
|
||||
endfunction
|
||||
|
||||
function! s:bitwise_rshift(a, n)
|
||||
let a = a:a < 0 ? a:a - 0x80000000 : a:a
|
||||
let a = a / s:k[a:n]
|
||||
if a:a < 0
|
||||
let a += 0x40000000 / s:k[a:n - 1]
|
||||
endif
|
||||
return a
|
||||
endfunction
|
||||
|
||||
function! s:bitwise_not(a)
|
||||
return -a:a - 1
|
||||
endfunction
|
||||
|
||||
function! s:bitwise_and(a, b)
|
||||
let a = a:a < 0 ? a:a - 0x80000000 : a:a
|
||||
let b = a:b < 0 ? a:b - 0x80000000 : a:b
|
||||
let r = 0
|
||||
let n = 1
|
||||
while a && b
|
||||
let r += s:and[a % 0x10][b % 0x10] * n
|
||||
let a = a / 0x10
|
||||
let b = b / 0x10
|
||||
let n = n * 0x10
|
||||
endwhile
|
||||
if (a:a < 0) && (a:b < 0)
|
||||
let r += 0x80000000
|
||||
endif
|
||||
return r
|
||||
endfunction
|
||||
|
||||
function! s:bitwise_or(a, b)
|
||||
let a = a:a < 0 ? a:a - 0x80000000 : a:a
|
||||
let b = a:b < 0 ? a:b - 0x80000000 : a:b
|
||||
let r = 0
|
||||
let n = 1
|
||||
while a || b
|
||||
let r += s:or[a % 0x10][b % 0x10] * n
|
||||
let a = a / 0x10
|
||||
let b = b / 0x10
|
||||
let n = n * 0x10
|
||||
endwhile
|
||||
if (a:a < 0) || (a:b < 0)
|
||||
let r += 0x80000000
|
||||
endif
|
||||
return r
|
||||
endfunction
|
||||
|
||||
function! s:bitwise_xor(a, b)
|
||||
let a = a:a < 0 ? a:a - 0x80000000 : a:a
|
||||
let b = a:b < 0 ? a:b - 0x80000000 : a:b
|
||||
let r = 0
|
||||
let n = 1
|
||||
while a || b
|
||||
let r += s:xor[a % 0x10][b % 0x10] * n
|
||||
let a = a / 0x10
|
||||
let b = b / 0x10
|
||||
let n = n * 0x10
|
||||
endwhile
|
||||
if (a:a < 0) != (a:b < 0)
|
||||
let r += 0x80000000
|
||||
endif
|
||||
return r
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
118
vim/bundle/webapi-vim/autoload/webapi/soap.vim
Normal file
118
vim/bundle/webapi-vim/autoload/webapi/soap.vim
Normal file
@@ -0,0 +1,118 @@
|
||||
" soap
|
||||
" Last Change: 2010-09-10
|
||||
" Maintainer: Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
" License: This file is placed in the public domain.
|
||||
" Reference:
|
||||
" http://tools.ietf.org/rfc/rfc4743.txt
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
function! s:soap_call(url, func, ...)
|
||||
let envelope = webapi#xml#createElement("soap:Envelope")
|
||||
let envelope.attr["xmlns:soap"] = "http://schemas.xmlsoap.org/soap/envelope/"
|
||||
let envelope.attr["xmlns:xsi"] = "http://www.w3.org/2001/XMLSchema-instance"
|
||||
|
||||
let body = webapi#xml#createElement("soap:Body")
|
||||
call add(envelope.child, body)
|
||||
let func = webapi#xml#createElement(a:func)
|
||||
call add(body.child, func)
|
||||
|
||||
let n = 1
|
||||
for a in a:000
|
||||
let arg = webapi#xml#createElement("param".n)
|
||||
let arg.attr["xsi:type"] = "xsd:string"
|
||||
call arg.value(a)
|
||||
call add(func.child, arg)
|
||||
let n += 1
|
||||
endfor
|
||||
|
||||
let str = '<?xml version="1.0" encoding="UTF-8"?>' . envelope.toString()
|
||||
let res = webapi#http#post(a:url, str)
|
||||
let dom = webapi#xml#parse(res.content)
|
||||
return s:parse_return(dom.find("return"))
|
||||
endfunction
|
||||
|
||||
function! s:parse_return(node)
|
||||
if a:node.attr["xsi:type"] =~ ":Array$"
|
||||
let arr = []
|
||||
for item in a:node.child
|
||||
call add(ret, s:parse_return(item.child)
|
||||
endfor
|
||||
let ret = arr
|
||||
elseif a:node.attr["xsi:type"] =~ ":Map$"
|
||||
let ret = {}
|
||||
for item in a:node.childNodes("item")
|
||||
let val = item.childNode("value")
|
||||
if val.attr["xsi:type"] =~ ":Map$"
|
||||
let ret[item.childNode("key").value()] = s:parse_return(val)
|
||||
else
|
||||
let ret[item.childNode("key").value()] = item.childNode("value").value()
|
||||
endif
|
||||
endfor
|
||||
else
|
||||
if len(a:node.child)
|
||||
let arr = []
|
||||
for item in a:node.child
|
||||
call add(arr, s:parse_return(item)
|
||||
endfor
|
||||
let ret = arr
|
||||
else
|
||||
let ret = s:parse_return(a:node)
|
||||
endif
|
||||
endif
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! s:get_convert_code(arg)
|
||||
let code = ''
|
||||
let arg = a:arg
|
||||
if arg.type == "xsd:string"
|
||||
let code .= "let ".arg.name." = a:".arg.name
|
||||
elseif arg.type == "xsd:int"
|
||||
let code .= "let ".arg.name." = 0+a:".arg.name
|
||||
elseif arg.type == "xsd:boolean"
|
||||
let code .= "let ".arg.name." = (0+a:".arg.name.") ? 'true' : 'false'"
|
||||
elseif arg.type == "xsd:float"
|
||||
let code .= "let ".arg.name." = nr2float(0+a:".arg.name.")"
|
||||
elseif arg.type =~ ":Array$"
|
||||
let code .= "let ".arg.name." = a:".arg.name
|
||||
else
|
||||
throw "unknown type:". arg.type
|
||||
endif
|
||||
return code
|
||||
endfunction
|
||||
|
||||
function! webapi#soap#proxy(url)
|
||||
let dom = webapi#xml#parseURL(a:url)
|
||||
let l:api = {}
|
||||
let action = dom.childNode("service").find("soap:address").attr["location"]
|
||||
let operations = dom.childNode("portType").childNodes("operation")
|
||||
for operation in operations
|
||||
let name = operation.attr["name"]
|
||||
let inp = substitute(operation.childNode("input").attr["message"], "^tns:", "", "")
|
||||
let out = substitute(operation.childNode("output").attr["message"], "^tns:", "", "")
|
||||
let message = dom.childNode("message", {"name": inp})
|
||||
let args = []
|
||||
for part in message.childNodes("part")
|
||||
call add(args, {"name": part.attr["name"], "type": part.attr["type"]})
|
||||
endfor
|
||||
let argnames = []
|
||||
let code = ""
|
||||
for arg in args
|
||||
call add(argnames, arg.name)
|
||||
let code .= " ".s:get_convert_code(arg)."\n"
|
||||
endfor
|
||||
let code .= " return s:soap_call(".string(action).", ".string(name).", ".join(argnames, ",").")\n"
|
||||
let source = "function! l:api.".name."(".join(argnames, ",").") dict\n"
|
||||
let source .= code
|
||||
let source .= "endfunction\n"
|
||||
exe source
|
||||
endfor
|
||||
return api
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
||||
56
vim/bundle/webapi-vim/autoload/webapi/ucs.vim
Normal file
56
vim/bundle/webapi-vim/autoload/webapi/ucs.vim
Normal file
@@ -0,0 +1,56 @@
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:utf8len = [
|
||||
\ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
\ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
\ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
\ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
\ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
\ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
\ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
\ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,0,0,
|
||||
\]
|
||||
|
||||
function! webapi#ucs#byte2nr(byte)
|
||||
let p = a:byte
|
||||
let n0 = char2nr(p[0])
|
||||
if n0 < 0x80
|
||||
return n0
|
||||
endif
|
||||
let l = s:utf8len[n0]
|
||||
let n1 = char2nr(p[1])
|
||||
if l > 1 && webapi#bit#and(n1, 0xc0) == 0x80
|
||||
if l == 2
|
||||
return webapi#bit#shift(webapi#bit#and(n0, 0x1f), 6) + webapi#bit#and(n1, 0x3f)
|
||||
endif
|
||||
let n2 = char2nr(p[2])
|
||||
if webapi#bit#and(n2, 0xc0) == 0x80
|
||||
if l == 3
|
||||
return webapi#bit#shift(webapi#bit#and(n0, 0x0f), 12) + webapi#bit#shift(webapi#bit#and(n1, 0x3f), 6) + webapi#bit#and(n2, 0x3f)
|
||||
endif
|
||||
let n3 = char2nr(p[3])
|
||||
if webapi#bit#and(n3, 0xc0) == 0x80
|
||||
if l == 4
|
||||
return webapi#bit#shift(webapi#bit#and(n0, 0x07), 18) + webapi#bit#shift(webapi#bit#and(n1, 0x3f), 12) + webapi#bit#shift(webapi#bit#and(n2, 0x3f), 6) + webapi#bit#and(n3, 0x3f)
|
||||
endif
|
||||
let n4 = char2nr(p[4])
|
||||
if webapi#bit#and(n4, 0xc0) == 0x80
|
||||
if (l == 5)
|
||||
return webapi#bit#shift(webapi#bit#and(n0, 0x03), 24) + webapi#bit#shift(webapi#bit#and(n1, 0x3f), 18) + webapi#bit#shift(webapi#bit#and(n2, 0x3f), 12) + webapi#bit#shift(webapi#bit#and(n3 & 0x3f), 6) + webapi#bit#and(n4, 0x3f)
|
||||
endif
|
||||
let n5 = char2nr(p[5])
|
||||
if webapi#bit#and(n5, 0xc0) == 0x80 && l == 6
|
||||
return webapi#bit#shift(webapi#bit#and(n0, 0x01), 30) + webapi#bit#shift(webapi#bit#and(n1, 0x3f), 24) + webapi#bit#shift(webapi#bit#and(n2, 0x3f), 18) + webapi#bit#shift(webapi#bit#and(n3, 0x3f), 12) + webapi#bit#shift(webapi#bit#and(n4, 0x3f), 6) + webapi#bit#and(n5, 0x3f)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
return n0
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
||||
320
vim/bundle/webapi-vim/autoload/webapi/xml.vim
Normal file
320
vim/bundle/webapi-vim/autoload/webapi/xml.vim
Normal file
@@ -0,0 +1,320 @@
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:template = { 'name': '', 'attr': {}, 'child': [] }
|
||||
|
||||
function! s:nr2byte(nr)
|
||||
if a:nr < 0x80
|
||||
return nr2char(a:nr)
|
||||
elseif a:nr < 0x800
|
||||
return nr2char(a:nr/64+192).nr2char(a:nr%64+128)
|
||||
else
|
||||
return nr2char(a:nr/4096%16+224).nr2char(a:nr/64%64+128).nr2char(a:nr%64+128)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:nr2enc_char(charcode)
|
||||
if &encoding == 'utf-8'
|
||||
return nr2char(a:charcode)
|
||||
endif
|
||||
let char = s:nr2byte(a:charcode)
|
||||
if strlen(char) > 1
|
||||
let char = strtrans(iconv(char, 'utf-8', &encoding))
|
||||
endif
|
||||
return char
|
||||
endfunction
|
||||
|
||||
function! s:nr2hex(nr)
|
||||
let n = a:nr
|
||||
let r = ""
|
||||
while n
|
||||
let r = '0123456789ABCDEF'[n % 16] . r
|
||||
let n = n / 16
|
||||
endwhile
|
||||
return r
|
||||
endfunction
|
||||
|
||||
function! s:decodeEntityReference(str)
|
||||
let str = a:str
|
||||
let str = substitute(str, '>', '>', 'g')
|
||||
let str = substitute(str, '<', '<', 'g')
|
||||
"let str = substitute(str, '"', '"', 'g')
|
||||
"let str = substitute(str, ''', "'", 'g')
|
||||
"let str = substitute(str, ' ', ' ', 'g')
|
||||
"let str = substitute(str, '¥', '\¥', 'g')
|
||||
let str = substitute(str, '&#x\([0-9a-fA-F]\+\);', '\=s:nr2enc_char("0x".submatch(1))', 'g')
|
||||
let str = substitute(str, '&#\(\d\+\);', '\=s:nr2enc_char(submatch(1))', 'g')
|
||||
let str = substitute(str, '&', '\&', 'g')
|
||||
return str
|
||||
endfunction
|
||||
|
||||
function! s:encodeEntityReference(str)
|
||||
let str = a:str
|
||||
let str = substitute(str, '&', '\&', 'g')
|
||||
let str = substitute(str, '>', '\>', 'g')
|
||||
let str = substitute(str, '<', '\<', 'g')
|
||||
let str = substitute(str, '"', '\"', 'g')
|
||||
"let str = substitute(str, "\n", '\
', 'g')
|
||||
"let str = substitute(str, '"', '"', 'g')
|
||||
"let str = substitute(str, "'", ''', 'g')
|
||||
"let str = substitute(str, ' ', ' ', 'g')
|
||||
return str
|
||||
endfunction
|
||||
|
||||
function! s:matchNode(node, cond)
|
||||
if type(a:cond) == 1 && a:node.name == a:cond
|
||||
return 1
|
||||
endif
|
||||
if type(a:cond) == 2
|
||||
return a:cond(a:node)
|
||||
endif
|
||||
if type(a:cond) == 3
|
||||
let ret = 1
|
||||
for l:R in a:cond
|
||||
if !s:matchNode(a:node, l:R) | let ret = 0 | endif
|
||||
unlet l:R
|
||||
endfor
|
||||
return ret
|
||||
endif
|
||||
if type(a:cond) == 4
|
||||
for k in keys(a:cond)
|
||||
if has_key(a:node.attr, k) && a:node.attr[k] == a:cond[k] | return 1 | endif
|
||||
endfor
|
||||
endif
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! s:template.childNode(...) dict
|
||||
for c in self.child
|
||||
if type(c) == 4 && s:matchNode(c, a:000)
|
||||
return c
|
||||
endif
|
||||
unlet c
|
||||
endfor
|
||||
return {}
|
||||
endfunction
|
||||
|
||||
function! s:template.childNodes(...) dict
|
||||
let ret = []
|
||||
for c in self.child
|
||||
if type(c) == 4 && s:matchNode(c, a:000)
|
||||
let ret += [c]
|
||||
endif
|
||||
unlet c
|
||||
endfor
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! s:template.value(...) dict
|
||||
if a:0
|
||||
let self.child = a:000
|
||||
return
|
||||
endif
|
||||
let ret = ''
|
||||
for c in self.child
|
||||
if type(c) <= 1 || type(c) == 5
|
||||
let ret .= c
|
||||
elseif type(c) == 4
|
||||
let ret .= c.value()
|
||||
endif
|
||||
unlet c
|
||||
endfor
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! s:template.find(...) dict
|
||||
for c in self.child
|
||||
if type(c) == 4
|
||||
if s:matchNode(c, a:000)
|
||||
return c
|
||||
endif
|
||||
unlet! ret
|
||||
let ret = c.find(a:000)
|
||||
if !empty(ret)
|
||||
return ret
|
||||
endif
|
||||
endif
|
||||
unlet c
|
||||
endfor
|
||||
return {}
|
||||
endfunction
|
||||
|
||||
function! s:template.findAll(...) dict
|
||||
let ret = []
|
||||
for c in self.child
|
||||
if type(c) == 4
|
||||
if s:matchNode(c, a:000)
|
||||
call add(ret, c)
|
||||
endif
|
||||
let ret += c.findAll(a:000)
|
||||
endif
|
||||
unlet c
|
||||
endfor
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
function! s:template.toString() dict
|
||||
let xml = '<' . self.name
|
||||
for attr in keys(self.attr)
|
||||
let xml .= ' ' . attr . '="' . s:encodeEntityReference(self.attr[attr]) . '"'
|
||||
endfor
|
||||
if len(self.child)
|
||||
let xml .= '>'
|
||||
for c in self.child
|
||||
if type(c) == 4
|
||||
let xml .= c.toString()
|
||||
elseif type(c) > 1
|
||||
let xml .= s:encodeEntityReference(string(c))
|
||||
else
|
||||
let xml .= s:encodeEntityReference(c)
|
||||
endif
|
||||
unlet c
|
||||
endfor
|
||||
let xml .= '</' . self.name . '>'
|
||||
else
|
||||
let xml .= ' />'
|
||||
endif
|
||||
return xml
|
||||
endfunction
|
||||
|
||||
function! webapi#xml#createElement(name)
|
||||
let node = deepcopy(s:template)
|
||||
let node.name = a:name
|
||||
return node
|
||||
endfunction
|
||||
|
||||
function! s:parse_tree(ctx, top)
|
||||
let node = a:top
|
||||
let stack = [a:top]
|
||||
let pos = 0
|
||||
" content accumulates the text only tags
|
||||
let content = ""
|
||||
let append_content_to_parent = 'if len(stack) && content != "" | call add(stack[-1].child, content) | let content ="" | endif'
|
||||
|
||||
let mx = '^\s*\(<?xml[^>]\+>\)'
|
||||
if a:ctx['xml'] =~ mx
|
||||
let match = matchstr(a:ctx['xml'], mx)
|
||||
let a:ctx['xml'] = a:ctx['xml'][stridx(a:ctx['xml'], match) + len(match):]
|
||||
let mx = 'encoding\s*=\s*["'']\{0,1}\([^"'' \t]\+\|[^"'']\+\)["'']\{0,1}'
|
||||
let matches = matchlist(match, mx)
|
||||
if len(matches)
|
||||
let encoding = matches[1]
|
||||
if len(encoding) && len(a:ctx['encoding']) == 0
|
||||
let a:ctx['encoding'] = encoding
|
||||
let a:ctx['xml'] = iconv(a:ctx['xml'], encoding, &encoding)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
" this regex matches
|
||||
" 1) the remaining until the next tag begins
|
||||
" 2) maybe closing "/" of tag name
|
||||
" 3) tagname
|
||||
" 4) the attributes of the text (optional)
|
||||
" 5) maybe closing "/" (end of tag name)
|
||||
" or
|
||||
" 6) CDATA or ''
|
||||
" 7) text content of CDATA
|
||||
" 8) the remaining text after the tag (rest)
|
||||
" (These numbers correspond to the indexes in matched list m)
|
||||
let tag_mx = '^\(\_.\{-}\)\%(\%(<\(/\?\)\([^!/>[:space:]]\+\)\(\%([[:space:]]*[^/>=[:space:]]\+[[:space:]]*=[[:space:]]*\%([^"'' >\t]\+\|"[^"]*"\|''[^'']*''\)\|[[:space:]]\+[^/>=[:space:]]\+[[:space:]]*\)*\)[[:space:]]*\(/\?\)>\)\|\%(<!\[\(CDATA\)\[\(.\{-}\)\]\]>\)\|\(<!--.\{-}-->\)\)\(.*\)'
|
||||
|
||||
while len(a:ctx['xml']) > 0
|
||||
let m = matchlist(a:ctx.xml, tag_mx)
|
||||
if empty(m) | break | endif
|
||||
let is_end_tag = m[2] == '/' && m[5] == ''
|
||||
let is_start_and_end_tag = m[2] == '' && m[5] == '/'
|
||||
let tag_name = m[3]
|
||||
let attrs = m[4]
|
||||
|
||||
if len(m[1])
|
||||
let content .= s:decodeEntityReference(m[1])
|
||||
endif
|
||||
|
||||
if is_end_tag
|
||||
" closing tag: pop from stack and continue at upper level
|
||||
exec append_content_to_parent
|
||||
|
||||
if len(stack) " TODO: checking whether opened tag is exist.
|
||||
call remove(stack, -1)
|
||||
endif
|
||||
let a:ctx['xml'] = m[9]
|
||||
continue
|
||||
endif
|
||||
|
||||
" comment tag
|
||||
if m[8] != ''
|
||||
let a:ctx.xml = m[9]
|
||||
continue
|
||||
endif
|
||||
|
||||
" if element is a CDATA
|
||||
if m[6] != ''
|
||||
let content .= m[7]
|
||||
let a:ctx.xml = m[9]
|
||||
continue
|
||||
endif
|
||||
|
||||
let node = deepcopy(s:template)
|
||||
let node.name = tag_name
|
||||
let attr_mx = '\([^=[:space:]]\+\)\s*\%(=\s*''\([^'']*\)''\|=\s*"\([^"]*\)"\|=\s*\(\w\+\)\|\)'
|
||||
while len(attrs) > 0
|
||||
let attr_match = matchlist(attrs, attr_mx)
|
||||
if len(attr_match) == 0
|
||||
break
|
||||
endif
|
||||
let name = attr_match[1]
|
||||
let value = len(attr_match[2]) ? attr_match[2] : len(attr_match[3]) ? attr_match[3] : len(attr_match[4]) ? attr_match[4] : ""
|
||||
if value == ""
|
||||
let value = name
|
||||
endif
|
||||
let node.attr[name] = s:decodeEntityReference(value)
|
||||
let attrs = attrs[stridx(attrs, attr_match[0]) + len(attr_match[0]):]
|
||||
endwhile
|
||||
|
||||
exec append_content_to_parent
|
||||
|
||||
if len(stack)
|
||||
call add(stack[-1].child, node)
|
||||
endif
|
||||
if !is_start_and_end_tag
|
||||
" opening tag, continue parsing its contents
|
||||
call add(stack, node)
|
||||
endif
|
||||
let a:ctx['xml'] = m[9]
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
function! webapi#xml#parse(xml)
|
||||
let top = deepcopy(s:template)
|
||||
let oldmaxmempattern=&maxmempattern
|
||||
let oldmaxfuncdepth=&maxfuncdepth
|
||||
let &maxmempattern=2000000
|
||||
let &maxfuncdepth=2000
|
||||
"try
|
||||
call s:parse_tree({'xml': a:xml, 'encoding': ''}, top)
|
||||
for node in top.child
|
||||
if type(node) == 4
|
||||
return node
|
||||
endif
|
||||
unlet node
|
||||
endfor
|
||||
"catch /.*/
|
||||
"endtry
|
||||
let &maxmempattern=oldmaxmempattern
|
||||
let &maxfuncdepth=oldmaxfuncdepth
|
||||
throw "Parse Error"
|
||||
endfunction
|
||||
|
||||
function! webapi#xml#parseFile(fname)
|
||||
return webapi#xml#parse(join(readfile(a:fname), "\n"))
|
||||
endfunction
|
||||
|
||||
function! webapi#xml#parseURL(url)
|
||||
return webapi#xml#parse(webapi#http#get(a:url).content)
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
||||
259
vim/bundle/webapi-vim/autoload/webapi/xmlrpc.vim
Normal file
259
vim/bundle/webapi-vim/autoload/webapi/xmlrpc.vim
Normal file
@@ -0,0 +1,259 @@
|
||||
" xmlrpc
|
||||
" Last Change: 2010-11-05
|
||||
" Maintainer: Yasuhiro Matsumoto <mattn.jp@gmail.com>
|
||||
" License: This file is placed in the public domain.
|
||||
" Reference:
|
||||
" http://tools.ietf.org/rfc/rfc3529.txt
|
||||
|
||||
let s:save_cpo = &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:system = function(get(g:, 'webapi#system_function', 'system'))
|
||||
|
||||
function! webapi#xmlrpc#nil()
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! webapi#xmlrpc#true()
|
||||
return 1
|
||||
endfunction
|
||||
|
||||
function! webapi#xmlrpc#false()
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! s:get_childNode(node)
|
||||
let child = a:node.childNode('value').childNode()
|
||||
if empty(child)
|
||||
let child = a:node.childNode('value')
|
||||
endif
|
||||
return child
|
||||
endfunction
|
||||
|
||||
function! s:from_value(value)
|
||||
let value = a:value
|
||||
if value.name == 'methodResponse'
|
||||
let param = value.childNode('params').childNodes('param')
|
||||
if len(param) == 1
|
||||
return s:from_value(s:get_childNode(param[0]))
|
||||
else
|
||||
let ret = []
|
||||
for v in param
|
||||
call add(ret, s:from_value(s:get_childNode(v)))
|
||||
endfor
|
||||
return ret
|
||||
endif
|
||||
elseif value.name == 'string'
|
||||
return value.value()
|
||||
elseif value.name == 'base64'
|
||||
return value.value()
|
||||
elseif value.name == 'dateTime.iso8601'
|
||||
return value.value()
|
||||
elseif value.name == 'boolean'
|
||||
return 0+substitute(value.value(), "[ \n\r]", '', 'g')
|
||||
elseif value.name == 'int'
|
||||
return 0+substitute(value.value(), "[ \n\r]", '', 'g')
|
||||
elseif value.name == 'i4'
|
||||
return 0+substitute(value.value(), "[ \n\r]", '', 'g')
|
||||
elseif value.name == 'double'
|
||||
return str2float(substitute(value.value(), "[ \n\r]", '', 'g'))
|
||||
elseif value.name == 'struct'
|
||||
let ret = {}
|
||||
for member in value.childNodes('member')
|
||||
let ret[member.childNode('name').value()] = s:from_value(s:get_childNode(member))
|
||||
endfor
|
||||
return ret
|
||||
elseif value.name == 'array'
|
||||
let ret = []
|
||||
for v in value.childNode('data').childNodes('value')
|
||||
let child = v.childNode()
|
||||
if !empty(child)
|
||||
call add(ret, s:from_value(child))
|
||||
else
|
||||
call add(ret, v.value())
|
||||
endif
|
||||
endfor
|
||||
return ret
|
||||
elseif value.name == 'nil'
|
||||
if get(g:, 'webapi#xmlrpc#allow_nil', 0) != 0
|
||||
return function('webapi#xmlrpc#nil')
|
||||
endif
|
||||
return 0
|
||||
elseif value.name == 'value'
|
||||
return value.value()
|
||||
else
|
||||
throw "unknown type: ".value.name
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:to_value(content)
|
||||
if type(a:content) == 4
|
||||
if has_key(a:content, 'bits')
|
||||
let struct = webapi#xml#createElement("struct")
|
||||
|
||||
let member = webapi#xml#createElement("member")
|
||||
call add(struct.child, member)
|
||||
let name = webapi#xml#createElement("name")
|
||||
call add(member.child, name)
|
||||
call name.value("name")
|
||||
let value = webapi#xml#createElement("value")
|
||||
call add(member.child, value)
|
||||
call add(value.child, s:to_value(a:content["name"]))
|
||||
|
||||
let member = webapi#xml#createElement("member")
|
||||
call add(struct.child, member)
|
||||
let name = webapi#xml#createElement("name")
|
||||
call name.value("bits")
|
||||
call add(member.child, name)
|
||||
let value = webapi#xml#createElement("value")
|
||||
call add(member.child, value)
|
||||
let base64 = webapi#xml#createElement("base64")
|
||||
call add(value.child, base64)
|
||||
if has_key(a:content, "bits") && len(a:content["bits"])
|
||||
call base64.value(a:content["bits"])
|
||||
elseif has_key(a:content, "path")
|
||||
let quote = &shellxquote == '"' ? "'" : '"'
|
||||
let bits = substitute(s:system("xxd -ps ".quote.a:content["path"].quote), "[ \n\r]", '', 'g')
|
||||
call base64.value(webapi#base64#b64encodebin(bits))
|
||||
endif
|
||||
return struct
|
||||
else
|
||||
let struct = webapi#xml#createElement("struct")
|
||||
for key in keys(a:content)
|
||||
let member = webapi#xml#createElement("member")
|
||||
let name = webapi#xml#createElement("name")
|
||||
call name.value(key)
|
||||
call add(member.child, name)
|
||||
let value = webapi#xml#createElement("value")
|
||||
call add(value.child, s:to_value(a:content[key]))
|
||||
call add(member.child, value)
|
||||
call add(struct.child, member)
|
||||
endfor
|
||||
return struct
|
||||
endif
|
||||
elseif type(a:content) == 3
|
||||
let array = webapi#xml#createElement("array")
|
||||
let data = webapi#xml#createElement("data")
|
||||
for item in a:content
|
||||
let value = webapi#xml#createElement("value")
|
||||
call add(value.child, s:to_value(item))
|
||||
call add(data.child, value)
|
||||
endfor
|
||||
call add(array.child, data)
|
||||
return array
|
||||
elseif type(a:content) == 2
|
||||
if a:content == function('webapi#xmlrpc#true')
|
||||
let true = webapi#xml#createElement("boolean")
|
||||
call true.value('true')
|
||||
return true
|
||||
elseif a:content == function('webapi#xmlrpc#false')
|
||||
let false = webapi#xml#createElement("boolean")
|
||||
call false.value('false')
|
||||
return false
|
||||
else
|
||||
return webapi#xml#createElement("nil")
|
||||
endif
|
||||
elseif type(a:content) <= 1 || type(a:content) == 5
|
||||
if type(a:content) == 0
|
||||
let int = webapi#xml#createElement("int")
|
||||
call int.value(a:content)
|
||||
return int
|
||||
elseif type(a:content) == 1
|
||||
let str = webapi#xml#createElement("string")
|
||||
call str.value(a:content)
|
||||
return str
|
||||
elseif type(a:content) == 5
|
||||
let double = webapi#xml#createElement("double")
|
||||
call double.value(a:content)
|
||||
return double
|
||||
endif
|
||||
endif
|
||||
return {}
|
||||
endfunction
|
||||
|
||||
function! s:to_fault(dom)
|
||||
let struct = a:dom.find('struct')
|
||||
let faultCode = ""
|
||||
let faultString = ""
|
||||
for member in struct.childNodes('member')
|
||||
if member.childNode('name').value() == "faultCode"
|
||||
let faultCode = member.childNode('value').value()
|
||||
elseif member.childNode('name').value() == "faultString"
|
||||
let faultString = member.childNode('value').value()
|
||||
endif
|
||||
endfor
|
||||
return faultCode.":".faultString
|
||||
endfunction
|
||||
|
||||
"add_node_params
|
||||
"Add list of args on the xml tree.
|
||||
"input: list of args
|
||||
"output: none
|
||||
function! s:add_node_params(args)
|
||||
let params = webapi#xml#createElement("params")
|
||||
for Arg in a:args
|
||||
let param = webapi#xml#createElement("param")
|
||||
let value = webapi#xml#createElement("value")
|
||||
call value.value(s:to_value(Arg))
|
||||
call add(param.child, value)
|
||||
call add(params.child, param)
|
||||
unlet Arg
|
||||
endfor
|
||||
return params
|
||||
endfunction
|
||||
|
||||
function! webapi#xmlrpc#call(uri, func, args)
|
||||
let methodCall = webapi#xml#createElement("methodCall")
|
||||
let methodName = webapi#xml#createElement("methodName")
|
||||
call methodName.value(a:func)
|
||||
call add(methodCall.child, methodName)
|
||||
if !empty(a:args)
|
||||
call add(methodCall.child, s:add_node_params(a:args))
|
||||
endif
|
||||
let xml = '<?xml version="1.0" encoding="utf-8"?>'
|
||||
let xml .= iconv(methodCall.toString(), &encoding, "utf-8")
|
||||
let res = webapi#http#post(a:uri, xml, {"Content-Type": "text/xml"})
|
||||
let dom = webapi#xml#parse(res.content)
|
||||
if len(dom.find('fault'))
|
||||
throw s:to_fault(dom)
|
||||
else
|
||||
return s:from_value(dom)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! webapi#xmlrpc#wrap(contexts)
|
||||
let api = {}
|
||||
for context in a:contexts
|
||||
let target = api
|
||||
let namespaces = split(context.name, '\.')[:-2]
|
||||
if len(namespaces) > 0
|
||||
for ns in namespaces
|
||||
if !has_key(target, ns)
|
||||
let target[ns] = {".uri": context.uri}
|
||||
endif
|
||||
let target = target[ns]
|
||||
let api['.uri'] = target['.uri']
|
||||
endfor
|
||||
endif
|
||||
if len(context.argnames) && context.argnames[-1] == '...'
|
||||
let arglist = '[' . join(map(copy(context.argnames[:-2]),'"a:".v:val'),',') . ']+a:000'
|
||||
else
|
||||
let arglist = '[' . join(map(copy(context.argnames),'"a:".v:val'),',') . ']'
|
||||
endif
|
||||
if has_key(context, 'alias')
|
||||
exe "function api.".context.alias."(".join(context.argnames,",").") dict\n"
|
||||
\. " return webapi#xmlrpc#call(self['.uri'], '".context.name."', ".arglist.")\n"
|
||||
\. "endfunction\n"
|
||||
else
|
||||
exe "function api.".context.name."(".join(context.argnames,",").") dict\n"
|
||||
\. " return webapi#xmlrpc#call('".context.uri."', '".context.name."', ".arglist.")\n"
|
||||
\. "endfunction\n"
|
||||
endif
|
||||
endfor
|
||||
return api
|
||||
endfunction
|
||||
|
||||
let &cpo = s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
||||
" vim:set et:
|
||||
Reference in New Issue
Block a user