Bunch of changes inspired by r00k

This commit is contained in:
2013-07-07 17:25:47 -04:00
parent c5a1ed1258
commit cf3eea13fb
141 changed files with 22472 additions and 519 deletions

View 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:

View 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

View 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:

View 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:

View 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

View 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, '&gt;', '>', 'g')
let str = substitute(str, '&lt;', '<', 'g')
let str = substitute(str, '&quot;', '"', 'g')
let str = substitute(str, '&apos;', "'", 'g')
let str = substitute(str, '&nbsp;', ' ', 'g')
let str = substitute(str, '&yen;', '\&#65509;', 'g')
let str = substitute(str, '&#\(\d\+\);', '\=s:nr2enc_char(submatch(1))', 'g')
let str = substitute(str, '&amp;', '\&', 'g')
let str = substitute(str, '&raquo;', '>', 'g')
let str = substitute(str, '&laquo;', '<', 'g')
return str
endfunction
function! webapi#html#encodeEntityReference(str)
let str = a:str
let str = substitute(str, '&', '\&amp;', 'g')
let str = substitute(str, '>', '\&gt;', 'g')
let str = substitute(str, '<', '\&lt;', 'g')
let str = substitute(str, "\n", '\&#x0d;', 'g')
let str = substitute(str, '"', '\&quot;', 'g')
let str = substitute(str, "'", '\&apos;', 'g')
let str = substitute(str, ' ', '\&nbsp;', '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:

View 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:

View 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:

View 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:

View 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:

View 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:

View 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

View 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:

View 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:

View 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, '&gt;', '>', 'g')
let str = substitute(str, '&lt;', '<', 'g')
"let str = substitute(str, '&quot;', '"', 'g')
"let str = substitute(str, '&apos;', "'", 'g')
"let str = substitute(str, '&nbsp;', ' ', 'g')
"let str = substitute(str, '&yen;', '\&#65509;', '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, '&amp;', '\&', 'g')
return str
endfunction
function! s:encodeEntityReference(str)
let str = a:str
let str = substitute(str, '&', '\&amp;', 'g')
let str = substitute(str, '>', '\&gt;', 'g')
let str = substitute(str, '<', '\&lt;', 'g')
let str = substitute(str, '"', '\&#34;', 'g')
"let str = substitute(str, "\n", '\&#x0d;', 'g')
"let str = substitute(str, '"', '&quot;', 'g')
"let str = substitute(str, "'", '&apos;', 'g')
"let str = substitute(str, ' ', '&nbsp;', '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:

View 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: