tpope / vim-unimpaired

unimpaired.vim: Pairs of handy bracket mappings
https://www.vim.org/scripts/script.php?script_id=1590
3.33k stars 203 forks source link

Feature request: unconditional URL encode (encode all chars) #207

Closed dkasak closed 4 years ago

dkasak commented 4 years ago

Currently, the URL encode feature ([u) only encodes characters which are reserved in a URL. However, I often want to percent-encode all characters.

Would you consider something like this? Seems like it would fit nicely on [U.

dkasak commented 4 years ago

I forgot to mention my use case for this: it's very useful for pentesting and websec work, for instance when editing a URL or constructing payloads in an attempt to exploit and/or bypass a WAF.

tpope commented 4 years ago

Unfortunately there's just not enough mappings to go around for all the numerous variants of the various encodings. For URL encoding, you could just as easily use [U for the query parameter variant that encodes spaces as + rather than %20, for example, or a variant that does the bare minimum like : and /, allowing insignificant punctuation and 8 bit characters through. I would consider both of those higher priority for a dedicated map than your more niche use case.

Fear not, though, as UnimpairedMapTransform is public, so you can create your own map in after/plugin/unimpaired.vim in just a few lines. The only catch is you need to use a public implementation function rather than a s: one.

dkasak commented 4 years ago

Fair enough!

Fear not, though, as UnimpairedMapTransform is public, so you can create your own map in after/plugin/unimpaired.vim in just a few lines. The only catch is you need to use a public implementation function rather than a s: one.

And thanks for this tip, this is indeed enough for me.

dkasak commented 4 years ago

Actually, putting the following in after/plugin/unimpaired.vim doesn't seem to work (no mapping seems to be generated):

function! UrlEncodeAll(str) abort
  return substitute(iconv(a:str, 'latin1', 'utf-8'),'.','\="%".printf("%02X",char2nr(submatch(0)))','g')
endfunction

call UnimpairedMapTransform('UrlEncodeAll', '[U')

Did I miss something?

tpope commented 4 years ago

Make sure it's in your runtimepath. ~/.vim/after/plugin/unimpaired.vim should work. Check :scriptnames and make sure it was loaded.

dkasak commented 4 years ago

I checked, it is loaded. I also tried doing the UnimpairedMapTransform call manually after vim starts up. It reports no errors, but the result is the same.

Interestingly, the <Plug> mappings seem to be created correctly:

n  <Plug>unimpaired_line_UrlEncodeAll * <SNR>57_TransformSetup("UrlEncodeAll")."_"                                                                                                                                                             
x  <Plug>unimpaired_UrlEncodeAll * <SNR>57_TransformSetup("UrlEncodeAll")                                                                                                                                                                      
n  <Plug>unimpaired_UrlEncodeAll * <SNR>57_TransformSetup("UrlEncodeAll")                                                                                                                                                                      

Just the [U mappings are missing. Creating them by hand makes it work, so I guess that's a possible workaround, but I'm not sure what's going wrong.

tpope commented 4 years ago

Goddammit it broke with d53b0bd6e3d204cff27df4262f6e37ee015f4b2c. You'll have to provide the actual [U map yourself until I get around to fixing this, which won't be any time soon.

dkasak commented 4 years ago

No worries, I'll just work around it for the time being.

Just in case anyone needs it, this is the full snippet to make it work:

function! UrlEncodeAll(str) abort
  return substitute(iconv(a:str, 'latin1', 'utf-8'),'.','\="%".printf("%02X",char2nr(submatch(0)))','g')
endfunction

call UnimpairedMapTransform('UrlEncodeAll', '[U')

nmap [U <Plug>unimpaired_UrlEncodeAll
xmap [U <Plug>unimpaired_UrlEncodeAll
nmap [UU <Plug>unimpaired_line_UrlEncodeAll