What is correct OAuth percent encoding? - oauth

I am working on implementing an Oauth Api and am discovering there are a few things I am having trouble validating, would love if anyone could provide clarification. Warning I probably will ramble so I will try to mark my questions in bold.
According to the oauth 1.0 spec https://www.rfc-editor.org/rfc/rfc5849, I am lead to believe that the way oauth params are percent encoded for signatures is different then when on the wire.
Section 3.6 https://www.rfc-editor.org/rfc/rfc5849#section-3.6
"It is used only in the construction of the signature base string and the "Authorization" header field."
RFC3986
https://www.rfc-editor.org/rfc/rfc3986
This appears to be the percent encoding scheme used in normal requests. However I did not see it give any sort of 'this' maps to 'that' so I am assuming if the character is in the reserved list the hexadecimal equivalent should be used.
Is the only difference that a ' '(Space) is %20 when encoded for signature? The Oauth spec makes reference to this, but I can't honestly find where that is defined in the other specs. It would be awesome if someone could point me to where that is mentioned and how I may have misunderstood it.
Should other white space characters be %20? Where in the spec does that mention that?
Is the conventional UrlEncode fine for form body and query params?
Finally I have some example output that I am looking to validate. I tried to show the difference between the Oauth Signature Encoded character and the Url encoded character. Once again the only differences appear to be the handling of the ' ', '*' and '~'
Char Oauth Url
* %2A *
~ ~ %7E
% %25 %25
! %21 %21
: %3A %3A
/ %2F %2F
= %3D %3D
& %26 %26
+ %2B %2B
%20 +
, %2C %2C
# %40 %40
\r\n %0D%0A %0D%0A
\n %0A %0A
\r %0D %0D
" %22 %22
? %3F %3F
( %28 %28
) %29 %29
| %7C %7C
[ %5B %5B
] %5D %5D

Although this is an old post would like to state my understanding all the same.
With regard to the percent-encoding as specified in the rfc3986#2.1, the understanding is that all characters other than the unreserved characters are to be escaped.
This means that other than :
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
The rest of the characters are to be encoded.
A sample implementation in java is provided here. Look for the percentEncode method that accepts a String as an argument.
public static String percentEncode(String s)
Additional code samples in other languages can be found here.

For JavaScript:
/**
* encodeURIComponent(str) Unescaped / Reserved characters:
*
* Alphabetic, Digit and -_.~!*'()
*
* oAuth Unescaped / Reserved characters:
*
* Alphabetic, Digit and -_.~
*
*/
// Encode with !*'()
this.oAuthEncode = function (value) {
value = encodeURIComponent(value)
value = value.replace(/!/g, '%21') // !
value = value.replace(/\*/g, '%2A') // *
value = value.replace(/'/g, '%27') // '
value = value.replace(/\)/g, '%29') // )
value = value.replace(/\(/g, '%28') // (
return value;
};
// Decode with !*'()
this.oAuthDecode = function (value) {
value = decodeURIComponent(value)
value = value.replace(/%21/g, '!') // !
value = value.replace(/%2A/g, '*') // *
value = value.replace(/%27/g, '\'') // '
value = value.replace(/%29/g, ')') // )
value = value.replace(/%28/g, '(') // (
return value;
};

Maybe this part of the Twitter developer docs might help you: https://developer.twitter.com/en/docs/basics/authentication/guides/percent-encoding-parameters.html

Related

Checking if a String container any of a set of Symbols in Dart

I would like to check if a string contains any of the following symbols ^ $ * . [ ] { } ( ) ? - " ! # # % & / \ , > < ' : ; | _ ~ ` + =
I tried using the following
string.contains(RegExp(r'[^$*.[]{}()?-"!##%&/\,><:;_~`+=]'))
But that does not seem to do anything. I am also not able to add the ' symbol.
Questions:
How do I check if a string contains any one of a set of symbols?
How do I add the ' symbol in my regex collection?
When writing such a RegExp pattern, you should escape the special symbols (if you want to search specifically by them).
Also, to add the ' to the RegExp, there is no straightforward way, but you could use String concatenation to work around this.
This is what the final result could look like:
void main() {
final regExp = RegExp(
r'[\^$*.\[\]{}()?\-"!##%&/\,><:;_~`+=' // <-- Notice the escaped symbols
"'" // <-- ' is added to the expression
']'
);
final string1 = 'abc';
final string2 = 'abc[';
final string3 = "'";
print(string1.contains(regExp)); // false
print(string2.contains(regExp)); // true
print(string3.contains(regExp)); // true
}
To ad both ' an " to the same string literal, you can use a multiline (triple-quoted) string.
string.contains(RegExp(r'''[^$*.[\]{}()?\-"'!##%&/\\,><:;_~`+=]'''))
You also need to escape characters which have meaning inside a RegExp character class (], - and \ in particular).
Another approach is to create a set of character codes, and check if the string's characters are in that set:
var chars = r'''^$*.[]{}()?-"'!##%&/\,><:;_~`+=''';
var charSet = {...chars.codeUnits};
var containsSpecialChar = string.codeUnits.any(charSet.contains);

Trying to add special character (%) sign to variable with following concatenation sign in ESQL, it gives me the the below error

Trying to add special character (%) sign to variable with following concatenation sign, but it gives me the the error: Invalid characters.
DECLARE Percent CHARACTER CAST ( ' %' AS CHARACTER CCSID 1208);
SET AlocatedAmount = 45
SET InPercent = AlocatedAmount||'%'
Result should be: InPercent = 45%
Error:Invalid characters::45 %
What's going wrong here?
AlocatedAmount seems to be an INTEGER, on what you cannot use the concatenation operator.
You need to cast that to CHARACTER first:
SET InPercent = CAST(AlocatedAmount AS CHARACTER) || '%';
So there is also the option of using FORMAT in your CAST
DECLARE Num INTEGER;
DECLARE FormattedStr CHAR;
SET Num = 45;
SET FormattedStr = CAST(Num AS CHAR FORMAT '#0%');
More information can be found at https://www.ibm.com/support/knowledgecenter/en/SSMKHH_9.0.0/com.ibm.etools.mft.doc/ak05615_.htm

Valid URL for an FTP site with username containing #

I want to create a valid URL to send to Windows File Explorer (or other file managers like TotalCommander) using the format:
ftp://username:password#ftp.domain.ext/folder/
In Explorer, it works with very straight username and password. But I receive errors (or Explorer just display the My Document instead of the FTP site) when password contains certain special characters. I played with URI encoding to encode the password with some success but not 100% reliable.
Can someone help me finding the correct requirements for a valid FTP URL including username and password? Thanks.
Here is a sample of the code using AutoHotkey "Run" command (on Windows 7 64-bit environment):
#NoEnv
#SingleInstance force
strFTPUrl := "ftp://www.jeanlalonde.ca"
strLoginName := "username#jeanlalonde.ca"
strPassword := "********"
StringReplace, strFTPUrl, strFTPUrl, % "ftp://", % "ftp://" . strLoginName . ":" . UriEncode(strPassword) . "#"
; Before: ftp://ftp.jeanlalonde.ca
; After: ftp://testaccount#jeanlalonde.ca:********#ftp.jeanlalonde.ca
MsgBox, %strFTPUrl%
Run, Explorer "%strFTPUrl%"
return
;------------------------------------------------------------
UriEncode(str)
; from GoogleTranslate by Mikhail Kuropyatnikov
; http://www.autohotkey.net/~sumon/GoogleTranslate.ahk
;------------------------------------------------------------
{
b_Format := A_FormatInteger
data := ""
SetFormat,Integer,H
SizeInBytes := StrPutVar(str,var,"utf-8")
Loop, %SizeInBytes%
{
ch := NumGet(var,A_Index-1,"UChar")
If (ch=0)
Break
if ((ch>0x7f) || (ch<0x30) || (ch=0x3d))
s .= "%" . ((StrLen(c:=SubStr(ch,3))<2) ? "0" . c : c)
Else
s .= Chr(ch)
}
SetFormat,Integer,%b_format%
return s
}
;------------------------------------------------------------
;------------------------------------------------------------
StrPutVar(string, ByRef var, encoding)
;------------------------------------------------------------
{
; Ensure capacity.
SizeInBytes := VarSetCapacity( var, StrPut(string, encoding)
; StrPut returns char count, but VarSetCapacity needs bytes.
* ((encoding="utf-16"||encoding="cp1200") ? 2 : 1) )
; Copy or convert the string.
StrPut(string, &var, encoding)
Return SizeInBytes
}
;------------------------------------------------------------
If there are special characters (# being one) in the username too (not only in the password), you have to URL-encode the username too, the same way you URL-encode the password.
That means you have to apply the UriEncode to strLoginName, the same way you apply it to strPassword.
And you need to update the UriEncode to encode the #, as it does not.
The code for # is 0x40.
if ((ch>0x7f) || (ch<0x30) || (ch=0x3d) || (ch=0x40))
(Though you can compare to # literally too: ch="#").

What standard produced hex-encoded characters with an extra "25" at the front?

I'm trying to integrate with ybp.com, a vendor of proprietary software for managing book ordering workflows in large libraries. It keeps feeding me URLs that contain characters encoded with an extra "25" in them. Like this book title:
VOLATILE KNOWING%253a PARENTS%252c TEACHERS%252c AND THE CENSORED STORY OF ACCOUNTABILITY IN AMERICA%2527S PUBLIC SCHOOLS.
The encoded characters in this sample are as follows:
%253a = %3A = a colon
%252c = %2C = a comma
%2527 = %27 = an apostrophe (non-curly)
I need to convert these encodings to a format my internal apps can recognize, and the extra 25 is throwing things off kilter. The final two digits of the hex encoded characters appear to be identical to standard URL encodings, so a brute force method would be to replace "%25" with "%". But I'm leary of doing that because it would be sure to haunt me later when an actual %25 shows up for some reason.
So, what standard is this? Is there an official algorithm for converting values like this to other encodings?
%25 is actually a % character. My guess is that the external website is URLEncoding their output twice accidentally.
If that's the case, it is safe to replace %25 with % (or just URLDecode twice)
The ASCII code 37 (25 in hexadecimal) is %, so the URL encoding of % is %25.
It looks like your data got URL encoded twice: , -> %2C -> %252C
Substituting every %25 for % should not generate any problems, as an actual %25 would get encoded to %25252525.
Create a counter that increments one by one for next two characters, and if you found modulus, you go back, assign the previous counter the '%' char and proceed again. Something like this.
char *str, *newstr; // Fill up with some memory before proceeding below..
....
int k = 0, j = 0;
short modulus = 0;
char first = 0, second = 0;
short proceed = 0;
for(k=0,j=0; k<some_size; j++,k++) {
if(str[k] == '%') {
++k; first = str[k];
++k; second = str[k];
proceed = 1;
} else if(modulus == 1) {
modulus = 0;
--j; first = str[k];
++k; second = str[k];
newstr[j] = '%';
proceed = 1;
} else proceed = 0; // Do not do decoding..
if(proceed == 1) {
if(first == '2' && second == '5') {
newstr[j] = '%';
modulus = 1;
......

How do I URL-escape a string in Mathematica?

For example,
urlesc["foo.cgi?abc=123"]
should return
foo.cgi%3Fabc%3D123
This is also known as percent-encoding.
Also, for better readability, spaces should encode to pluses.
I believe that's always acceptable for URL escaping.
Another method, using J/Link and java.net.URLEncoder:
In[116]:= Needs["JLink`"]; InstallJava[];
LoadJavaClass["java.net.URLEncoder"];
In[118]:= URLEncoder`encode["foo.cgi?abc=123"]
Out[118]= "foo.cgi%3Fabc%3D123"
There's also java.net.URLDecoder for decoding.
Here's my solution:
cat = StringJoin##(ToString/#{##})&; (* Like sprintf/strout in C/C++. *)
re = RegularExpression;
hex = IntegerString[#,16]&; (* integer to hex, represented as a string *)
up = ToUpperCase;
asc = ToCharacterCode[#][[1]]&; (* character to ascii code *)
subst = StringReplace;
urlesc[s_String] := subst[s, {" "->"+", re#"[^\w\_\:\.]":>"%"<>up#hex#asc#"$0"}]
urlesc[x_] := urlesc#cat#x
unesc[s_String] := subst[s, re#"\\%(..)":>FromCharacterCode#FromDigits["$1",16]]
As a bonus, here's a function to encode a list of rules like {a->2, b->3} into GET parameters like a=2&b=3, with appropriate URL-encoding:
encode[c_] := cat ## Riffle[cat[#1, "=", urlesc[#2]]& ### c, "&"]

Resources