Valid URL for an FTP site with username containing # - url

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="#").

Related

Would appreciate some help in identifying the language from this snippet

newbie question here, I'm trying to reuse a code, but since I'm not a programmer I couldn't identify it. I tried googling already some "programming language identifier by syntax" and googling some of the syntax in it and at first I thought it matched vb.net but upon downloading and opening a project there, it had too many syntax errors IIRC, so I don't think this is it.
Here's the snippet:
;==============================================================================================================================
; Function: _MemoryReadStdString($address, $handle, [, $offset=False])
;
; Description: Read memory for string. If str_length > 15 read pointer else read str.
;
; Parameter(s): $address - Address in memory to read.
; $handle - An array containing the Dll handle and the handle of the open
; process as returned by _MemoryOpen().
; $offset - If we wanna read pointer put offset in hex value example:
; $offset[2] = [0x20, 0x264]
;
; Return Value(s): On Success - Returns string value
; On Failure - Returns empty string ''
;
; Author(s): Ascer
;===============================================================================================================================
Func _MemoryReadStdString ($address, $handle, $offset)
; read memory for address of our name and return address to this name.
Local $addr_start = '0x' & Hex(_MemoryPointerRead($address, $handle, $offset)[0], 8) ;==> example 0x8A16308
; read memory for name length, just one byte
Local $str_length = _MemoryRead($addr_start + 0x10, $handle, 'byte') ;==> 0x8A16308 + 0x10 = 0x8A16318
; check if string < 16 then read name from $addr_start
If $str_length < 16 Then
Return BinaryToString(_MemoryRead($addr_start, $handle, 'char[15]')) ;==> 'King Medivius'
; string length is > 15 then we must read memory($addr_start) for new address
Else
$str_pointer = '0x' & Hex(_MemoryRead($addr_start, $handle), 8) ;==> example 0x8C95320
Return BinaryToString(_MemoryRead($str_pointer, $handle, 'char[32]')) ;==> read memory in $str_pointer region to get true name
EndIf
; return empty string if nothing found
Return ""
EndFunc
Sorry about the "EndFunc" there, it's inside the "pre code" but somehow ended up outside it. Any help is appreciated! Thanks!
Googling a portion of the code reveals a possible source at this post about what seems to be a Tibia private server named Medivia.
From the context it seems to be written in AutoIt - there is a screenshot near the bottom of the post showing the user testing code using a program named AutoIt3.exe Here is the download link.

How remove \n from lines

file, _ := os.Open("x.txt")
f := bufio.NewReader(file)
for {
read_line, _ := ReadString('\n')
fmt.Print(read_line)
// other code what work with parsed line...
}
end it add \n on every line , end program to work , only work with last line...
Please put example, i try anything end any solution what i find here not work for me.
You can slice off the last character:
read_line = read_line[:len(read_line)-1]
Perhaps a better approach is to use the strings library:
read_line = strings.TrimSuffix(read_line, "\n")
If you want to read a file line-by-line, using bufio.Scanner will be easier. Scanner won't includes endline (\n or \r\n) into the line.
file, err := os.Open("yourfile.txt")
if err != nil {
//handle error
return
}
defer file.Close()
s := bufio.NewScanner(file)
for s.Scan() {
read_line := s.Text()
// other code what work with parsed line...
}
If you want to remove endline, I suggest you to use TrimRightFunc, i.e.
read_line = strings.TrimRightFunc(read_line, func(c rune) bool {
//In windows newline is \r\n
return c == '\r' || c == '\n'
})
Update:
As pointed by #GwynethLlewelyn, using TrimRight will be simpler (cleaner), i.e.
read_line = strings.TrimRight(read_line, "\r\n")
Internally, TrimRight function call TrimRightFunc, and will remove the character if it match any character given as the second argument of TrimRight.
Clean and Simple Approach
You can also use the strings.TrimSpace() function which will also remove any extra trailing or leading characters like the ones of regex \n, \r and this approach is much more cleaner.
read_line = strings.TrimSpace(read_line)
Go doc: https://pkg.go.dev/strings#TrimSpace

TIdTCPClient Write Bytes

if _msg.isRequest then
begin
req:= THTTPRequest(_msg);
msgBody:= req.getMessageBody;
// Adds the URI line.
str:= str + req.getMethod + ' ';
str:= str + req.getURI + ' ';
str:= str + versionText + CRLF;
// Sets the content length header if its a POST
if req.getMethod = 'POST' then
req.setHeader(THTTPHeaderKey.CONTENT_LENGTH.ToString, IntToStr(Length(msgBody) * SizeOf(Char)));
// Adds the headers
for i:= 0 to req.getHeaders.Count -1 do
str:= str + req.getHeaders.Names[i] + '=' + req.getHeaders.ValueFromIndex[i];
str:= str + CRLF;
// Adds the message body if its POST
if req.getMethod = 'POST' then
str:= str + msgBody;
// Writes the result to the output stream.
formPopupRemote.IdTCPClient1.IOHandler.Write(Byte(str)); -> ERROR LINE
// formPopupRemote.HTTP.Get(str, stream);
end
else
ShowMessage('Responses sending not yet supported!');
end;
I want to writes the result to the IOHandler. But how can i do this, i converted this code from JAVA.
Here is Java Codes :
if (_msg.isRequest()) {
HTTPRequest req = (HTTPRequest) _msg;
String msgBody = req.getMessageBody();
// Adds the URI line.
str.append(req.getMethod() + " ");
str.append(req.getURI() + " ");
str.append(versionText + CRLF);
// Sets the content length header if its a POST
if (req.getMethod() == HTTPRequest.Method.POST)
req.setHeader(HTTPHeaderKey.CONTENT_LENGTH.toString(), String.valueOf(msgBody.getBytes().length));
// Adds the headers
for (String key : req.getHeaders())
str.append(key + ": " + req.getHeader(key) + CRLF);
str.append(CRLF);
// Adds the message body if its POST
if (req.getMethod() == HTTPRequest.Method.POST)
str.append(msgBody);
// Writes the result to the output stream.
getOutputStream().write(str.toString().getBytes());
} else {
throw new ProtocolException("Responses sending not yet supported!");
}
}
Actually i want to convert to Delphi from Java codes. But i couldn' t find outputstream equals in Delphi. Because TIdClient.IOHandler.Write has no TBytes parameter or array of Byte. But outputstream' s parameter is array of byte. So how should i write str?
TIdIOHandler has a Write() overload that accepts a String as input, so you don't need to manually convert to bytes at all:
formPopupRemote.IdTCPClient1.IOHandler.Write(str);
But if you did, Indy has overloaded ToBytes() functions for that purpose, and one of them accepts a String as input:
formPopupRemote.IdTCPClient1.IOHandler.Write(ToBytes(str));
However, this is overkill, since this is essentially what TIdIOHandelr.Write(String) does internally for you.
That being said, you really should be using the TIdHTTP component instead of manually formatting an HTTP request and using TIdTCPClient to send it. TIdHTTP has Get() and Post() methods (amongst others). All you have to do is pass in the full URL, and in the case of Post() also pass in a TStream object containing the raw body data. TIdHTTP also has properties for customing the request so you can set things like HTTP version (TIdHTTP.ProtocolVersion), body Content Type (TIdHTTP.Request.ContentType) and charset (TIdHTTP.Request.Charset), custom request headers (TIdHTTP.Request.CustomHeaders), etc. TIdHTTP will handle the Content-Length header for you automatically.

What is correct OAuth percent encoding?

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

how do i decode, change, then re-encode a CORBA IOR file (Visibroker) in my Java client code?

I am writing code to ingest the IOR file generated by the team responsible for the server and use it to bind my client to their object. Sounds easy, right?
For some reason a bit beyond my grasp (having to do with firewalls, DMZs, etc.), the value for the server inside the IOR file is not something we can use. We have to modify it. However, the IOR string is encoded.
What does Visibroker provide that will let me decode the IOR string, change one or more values, then re-encode it and continue on as normal?
I've already looked into IORInterceptors and URL Naming but I don't think either will do the trick.
Thanks in advance!
When you feel like you need to hack an IOR, resist the urge to do so by writing code and whatnot to mangle it to your liking. IORs are meant to be created and dictated by the server that contains the referenced objects, so the moment you start mucking around in there, you're kinda "voiding your warranty".
Instead, spend your time finding the right way to make the IOR usable in your environment by having the server use an alternative hostname when it generates them. Most ORBs offer such a feature. I don't know Visibroker's particular configuration options at all, but a quick Google search revealed this page that shows a promising value:
vbroker.se.iiop_ts.host
Specifies the host name used by this server engine.
The default value, null, means use the host name from the system.
Hope that helps.
Long time ago I wrote IorParser for GNU Classpath, the code is available. It is a normal parser written being aware about the format, should not "void a warranty" I think. IOR contains multiple tagged profiles that are encapsulated very much like XML so we could parse/modify profiles that we need and understand and leave the rest untouched.
The profile we need to parse is TAG_INTERNET_IOP. It contains version number, host, port and object key. Code that reads and writes this profile can be found in gnu.IOR class. I am sorry this is part of the system library and not a nice piece of code to copy paste here but it should not be very difficult to rip it out with a couple of dependent classes.
This question has been repeatedly asked as CORBA :: Get the client ORB address and port with use of IIOP
Use the FixIOR tool (binary) from jacORB to patch the address and port of an IOR. Download the binary (unzip it) and run:
fixior <new-address> <new-port> <ior-file>
The tool will override the content of the IOR file with the 'patched' IOR
You can use IOR Parser to check the resulting IOR and compare it to your original IOR
Use this function to change the IOR. pass stringified IOR as first argument.
void hackIOR(const char* str, char* newIOR )
{
size_t s = (str ? strlen(str) : 0);
char temp[1000];
strcpy(newIOR,"IOR:");
const char *p = str;
s = (s-4)/2; // how many octets are there in the string
p += 4;
int i;
for (i=0; i<(int)s; i++) {
int j = i*2;
char v=0;
if (p[j] >= '0' && p[j] <= '9') {
v = ((p[j] - '0') << 4);
}
else if (p[j] >= 'a' && p[j] <= 'f') {
v = ((p[j] - 'a' + 10) << 4);
}
else if (p[j] >= 'A' && p[j] <= 'F') {
v = ((p[j] - 'A' + 10) << 4);
}
else
cout <<"invalid octet"<<endl;
if (p[j+1] >= '0' && p[j+1] <= '9') {
v += (p[j+1] - '0');
}
else if (p[j+1] >= 'a' && p[j+1] <= 'f') {
v += (p[j+1] - 'a' + 10);
}
else if (p[j+1] >= 'A' && p[j+1] <= 'F') {
v += (p[j+1] - 'A' + 10);
}
else
cout <<"invalid octet"<<endl;
temp[i]=v;
}
temp[i] = 0;
// Now temp has decoded IOR string. print it.
// Replace the object ID in temp.
// Encoded it back, with following code.
int temp1,temp2;
int l,k;
for(k = 0, l = 4 ; k < s ; k++)
{
temp1=temp2=temp[k];
temp1 &= 0x0F;
temp2 = temp2 & 0xF0;
temp2 = temp2 >> 4;
if(temp2 >=0 && temp2 <=9)
{
newIOR[l++] = temp2+'0';
}
else if(temp2 >=10 && temp2 <=15)
{
newIOR[l++] = temp2+'A'-10;
}
if(temp1 >=0 && temp1 <=9)
{
newIOR[l++] = temp1+'0';
}
else if(temp1 >=10 && temp1 <=15)
{
newIOR[l++] = temp1+'A'-10;
}
}
newIOR[l] = 0;
//new IOR is present in new variable newIOR.
}
Hope this works for you.

Resources