Schnelles URLEncode mit WinAPI
Schnelles URLEncode mit WinAPI
Hi!
Ich brauche dringend ein URLEncode, das mit der aktuellen PB-Version läuft und so maschinennahe wie möglich ist.
Die in PB programmierten URLEncodes, die ich so finden konnte, sind unendlich langsam und legen den Computer Minuten lang lahm, wenn es um richtig lange Strings geht und genau solche habe ich aber.
Da ich mit der WinAPI bisher null Erfahrung habe, meine Bitte:
Kann mir bitte jemand anhand eines Codebeispiels verraten, wie ich die URLEncode-Funktion, die es angeblich in der WinAPI gibt, konkret aufrufe?
PS: Alternativ wäre natürlich auch eine selbstgebaute ASM-Bibliotheksfunktion denkbar - aber auch da konnte ich nichts finden, das mit PB4 läuft.
Danke!
Ich brauche dringend ein URLEncode, das mit der aktuellen PB-Version läuft und so maschinennahe wie möglich ist.
Die in PB programmierten URLEncodes, die ich so finden konnte, sind unendlich langsam und legen den Computer Minuten lang lahm, wenn es um richtig lange Strings geht und genau solche habe ich aber.
Da ich mit der WinAPI bisher null Erfahrung habe, meine Bitte:
Kann mir bitte jemand anhand eines Codebeispiels verraten, wie ich die URLEncode-Funktion, die es angeblich in der WinAPI gibt, konkret aufrufe?
PS: Alternativ wäre natürlich auch eine selbstgebaute ASM-Bibliotheksfunktion denkbar - aber auch da konnte ich nichts finden, das mit PB4 läuft.
Danke!
In der WinAPI heisst die Funktion offenbar UrlEscapeA, soviel habe ich schon mal rausgefunden. Ein erster Versuch produziert zwar keinen Fehler, aber ist auch nicht sehr aktiv:
String$ = "test=blabla@123"
If OpenLibrary(0, "shlwapi.dll")
CallFunction(0, "UrlEscapeA", @String$, 0, 0, 0)
CloseLibrary(0)
EndIf
Debug String$
Ich habe leider keine Erfahrung mit der API - irgendwo hockt da sicher ein schwerer Denkfehler.
Ich habe jetzt ein Beispiel für die Nutzung von UrlEscape gefunden, allerdings nicht in PB:
'//URL Encode Demo
strEncodedURL = Space$(MAX_PATH)
ret = UrlEscape(strURL, strEncodedURL, MAX_PATH, URL_DONT_SIMPLIFY)
If ret = 0 Then
strEncodedURL = Left$(strEncodedURL, MAX_PATH)
MsgBox "Encoded URL : " & vbCrLf & strEncodedURL
End If
Offensichtlich ist der erste übergebene String die Quelle und der zweite String das Ziel nach der Kodierung, in PB könnte es daher so ähnlich aussehen:
String1$ = "test=blabla@-+123"
If OpenLibrary(0, "shlwapi.dll")
String2$ = " "
ret = CallFunction(0,"UrlEscape", String1$, String2$, 30, #URL_DONT_SIMPLIFY)
Debug ret
Debug String1$
Debug String2$
CloseLibrary(0)
EndIf
Wie genau sind die Strings zu übergeben? Wie gesagt, ist der erste String ein Input, der zweite sollte ev. ein Zeiger sein @String2$ ??
Mit oder ohne @s bei beiden Strings ist das Ergebnis derzeit immer das gleiche: String1 ist nachher unverändert und String2 bleibt leer.
Der Rückgabewert ret ist 0, was ja an sich ein gutes Zeichen sein sollte.
String$ = "test=blabla@123"
If OpenLibrary(0, "shlwapi.dll")
CallFunction(0, "UrlEscapeA", @String$, 0, 0, 0)
CloseLibrary(0)
EndIf
Debug String$
Ich habe leider keine Erfahrung mit der API - irgendwo hockt da sicher ein schwerer Denkfehler.
Ich habe jetzt ein Beispiel für die Nutzung von UrlEscape gefunden, allerdings nicht in PB:
'//URL Encode Demo
strEncodedURL = Space$(MAX_PATH)
ret = UrlEscape(strURL, strEncodedURL, MAX_PATH, URL_DONT_SIMPLIFY)
If ret = 0 Then
strEncodedURL = Left$(strEncodedURL, MAX_PATH)
MsgBox "Encoded URL : " & vbCrLf & strEncodedURL
End If
Offensichtlich ist der erste übergebene String die Quelle und der zweite String das Ziel nach der Kodierung, in PB könnte es daher so ähnlich aussehen:
String1$ = "test=blabla@-+123"
If OpenLibrary(0, "shlwapi.dll")
String2$ = " "
ret = CallFunction(0,"UrlEscape", String1$, String2$, 30, #URL_DONT_SIMPLIFY)
Debug ret
Debug String1$
Debug String2$
CloseLibrary(0)
EndIf
Wie genau sind die Strings zu übergeben? Wie gesagt, ist der erste String ein Input, der zweite sollte ev. ein Zeiger sein @String2$ ??
Mit oder ohne @s bei beiden Strings ist das Ergebnis derzeit immer das gleiche: String1 ist nachher unverändert und String2 bleibt leer.
Der Rückgabewert ret ist 0, was ja an sich ein gutes Zeichen sein sollte.
Sind die PB Codes denn wirklich so lahm?
Muss es denn unbedingt API sein und nichts anderes?
Welche Zeichen müssen denn ersetzt werden? Alle oder nur bestimmte Zeichen, wie sie auch vom Browser ersetzt werden?
Wenn nämlich zum Beispiel a-z A-Z 0-9 nicht encodiert werden brauchen, dann reicht es doch, wenn du mit einer Schleife und ReplaceString() rangehst.
Code folgt gleich.
Edit:Ersetzt alles außer alphanumerische Zeichen (a-z A-Z 0-9). Meinste die API kann das so viel schneller, obwohl (vielleicht) nur derselbe Code hintersteckt?
Muss es denn unbedingt API sein und nichts anderes?
Welche Zeichen müssen denn ersetzt werden? Alle oder nur bestimmte Zeichen, wie sie auch vom Browser ersetzt werden?
Wenn nämlich zum Beispiel a-z A-Z 0-9 nicht encodiert werden brauchen, dann reicht es doch, wenn du mit einer Schleife und ReplaceString() rangehst.
Code folgt gleich.
Edit:
Code: Alles auswählen
Procedure.s url_encode(text$)
Protected n
text$=ReplaceString(text$, "%", "%25")
For n=1 To 255
If Not (n = '%' Or (n >= '0' And n <= '9') Or (n >= 'A' And n <= 'Z') Or (n >= 'a' And n <= 'z')) And FindString(text$, Chr(n), 1)
text$=ReplaceString(text$, Chr(n), "%"+RSet(Hex(n), 2, "0"))
EndIf
Next
ProcedureReturn text$
EndProcedure
Debug url_encode("a-z A-Z 0-9 dürfen%nicht ersetzt werden!!!")
Zuletzt geändert von AND51 am 24.10.2007 15:35, insgesamt 1-mal geändert.
PB 4.30
Code: Alles auswählen
Macro Happy
;-)
EndMacro
Happy End
Raten bringt dich so garantiert nicht weiter, schau dir malWernerZ hat geschrieben: Offensichtlich ist der erste übergebene String die Quelle und der zweite String das Ziel nach der Kodierung, in PB könnte es daher so ähnlich aussehen:
die Dokumentation des Befehls an :
http://66.102.9.104/search?q=cache:MXy9 ... cd=1&gl=de
Hab dein Edit nicht gesehen, WenerZ. Vielleicht schaust du dir ja doch nochmal mein Beispiel an.
Es ist übrigens kein Problem, meine Prozedur so umzustricken, dass ihr ein Pointer statt der String selbst übergeben wird. Und statt ProcedureReturn könnte meine Prozedur das Ergebnis auch irgendwo hin-pointern.
Es ist übrigens kein Problem, meine Prozedur so umzustricken, dass ihr ein Pointer statt der String selbst übergeben wird. Und statt ProcedureReturn könnte meine Prozedur das Ergebnis auch irgendwo hin-pointern.
PB 4.30
Code: Alles auswählen
Macro Happy
;-)
EndMacro
Happy End
AND51 hat geschrieben:Sind die PB Codes denn wirklich so lahm?
Muss es denn unbedingt API sein und nichts anderes?
Welche Zeichen müssen denn ersetzt werden? Alle oder nur bestimmte Zeichen, wie sie auch vom Browser ersetzt werden?
Wenn nämlich zum Beispiel a-z A-Z 0-9 nicht encodiert werden brauchen, dann reicht es doch, wenn du mit einer Schleife und ReplaceString() rangehst.
Code folgt gleich.
Edit:Ersetzt alles außer alphanumerische Zeichen (a-z A-Z 0-9). Meinste die API kann das so viel schneller, obwohl (vielleicht) nur derselbe Code hintersteckt?Code: Alles auswählen
Procedure.s url_encode(text$) Protected n text$=ReplaceString(text$, "%", "%25") For n=1 To 255 If Not (n = '%' Or (n >= '0' And n <= '9') Or (n >= 'A' And n <= 'Z') Or (n >= 'a' And n <= 'z')) And FindString(text$, Chr(n), 1) text$=ReplaceString(text$, Chr(n), "%"+RSet(Hex(n), 2, "0")) EndIf Next ProcedureReturn text$ EndProcedure Debug url_encode("a-z A-Z 0-9 dürfen%nicht ersetzt werden!!!")
Danke! Aber mit einem Code in ähnlicher Form hab ich's schon probiert und auch andere Versionen, die so in den Foren kursieren.
Das Problem ist, dass ich sehr große Mengen POSTen (und vorher kodieren) muss. In der Realität bedeutet das, dass der Rechner bei rund 250kB minutenlang praktisch blockiert ist (schwankt natürlich stark mit der Rechnerleistung, aber bei meinem Notebook sinds mehr als 2 Minuten - und wie gesagt, der Rechner ist derweil unbedienbar).
Dann müsstest du den Code manuell mit Hilfe eines Pointers durchgehen (parsen) und jedes unerwünsche Zeichen ersetzen. Es dürfte vermutlich um einiges schneller sein, den Code linear auf alle zeichen zu prüfen, als jedes Zeichen zu suchen und zu ersetzen.
Edit: Lass bei meinem Code mal das FindString() weg. Denn ReplaceString() hat ja schon ein FindString() eingebaut, sonst könnte er ja keine Strings suchen, um sie zu ersetzen. Das dürfte meinen Code noch etwas schneller machen.
Außerdem ist es nicht nötig, einen Parallelthread im englsichen Forum zu eröffnen, denn dadurch fühlen sich beide Boards etwas vor den Kopf gestoßen, wenn beide dir eine Lösung präsentieren und du nur eines (oder im Endeffekt keines) von beiden annimmst......
Edit: Lass bei meinem Code mal das FindString() weg. Denn ReplaceString() hat ja schon ein FindString() eingebaut, sonst könnte er ja keine Strings suchen, um sie zu ersetzen. Das dürfte meinen Code noch etwas schneller machen.
Außerdem ist es nicht nötig, einen Parallelthread im englsichen Forum zu eröffnen, denn dadurch fühlen sich beide Boards etwas vor den Kopf gestoßen, wenn beide dir eine Lösung präsentieren und du nur eines (oder im Endeffekt keines) von beiden annimmst......
PB 4.30
Code: Alles auswählen
Macro Happy
;-)
EndMacro
Happy End
edel hat geschrieben:Raten bringt dich so garantiert nicht weiter, schau dir malWernerZ hat geschrieben: Offensichtlich ist der erste übergebene String die Quelle und der zweite String das Ziel nach der Kodierung, in PB könnte es daher so ähnlich aussehen:
die Dokumentation des Befehls an :
http://66.102.9.104/search?q=cache:MXy9 ... cd=1&gl=de
Danke!
Für den Code habe ich ja ein Beispiel gefunden und kenne die Parameter des API-Befehls - mein Problem ist eher die Umsetzung in PB, bzw. die Parameterübergabe und -rückgabe.
AND51 hat geschrieben:Dann müsstest du den Code manuell mit Hilfe eines Pointers durchgehen (parsen) und jedes unerwünsche Zeichen ersetzen. Es dürfte vermutlich um einiges schneller sein, den Code linear auf alle zeichen zu prüfen, als jedes Zeichen zu suchen und zu ersetzen.
Edit: Lass bei meinem Code mal das FindString() weg. Denn ReplaceString() hat ja schon ein FindString() eingebaut, sonst könnte er ja keine Strings suchen, um sie zu ersetzen. Das dürfte meinen Code noch etwas schneller machen.
Außerdem ist es nicht nötig, einen Parallelthread im englsichen Forum zu eröffnen, denn dadurch fühlen sich beide Boards etwas vor den Kopf gestoßen, wenn beide dir eine Lösung präsentieren und du nur eines (oder im Endeffekt keines) von beiden annimmst......
Danke - der Code ist wesentlich schneller, als die, die ich gefunden hatte!
Die Idee ist viel schlauer - die anderen Codes gehen den String Zeichen für Zeichen durch und ersetzten es brav oder auch nicht.
Du gehst die Zeichenliste durch und ersetzt alle Vorkommen im String - das ist vielleicht bei ganz kleinen Strings etwas langsamer, aber bei großen ganz wesentlich flotter.
Gute Sache...

Hi WernerZ,
so wie ich sehe hast du schon eine lösung für dein problem,
ich habe trotzdem das mit api umgesetzt.
hier ein beispiel von VB portiert!
Ciao
jpd
so wie ich sehe hast du schon eine lösung für dein problem,
ich habe trotzdem das mit api umgesetzt.
hier ein beispiel von VB portiert!
Ciao
jpd
Code: Alles auswählen
Declare.s EncodeUrl(sUrl.s)
Declare.s DecodeUrl(sUrl.s)
Enumeration
#EncodeUrl
#UrlUnescape
EndEnumeration
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
;idea ------->>>http://vbnet.mvps.org/index.html?code/network/netconnectionenum.htm
;------------->By Randy Birch
;''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
;Purebasic 4.02/4.10 b4
;
;converted by jpd
;
;Unicode ON
#MAX_PATH = 260
#ERROR_SUCCESS = 0
;'Treat entire URL param as one URL segment
#URL_ESCAPE_SEGMENT_ONLY = 8192
#URL_ESCAPE_PERCENT = 4096
#URL_UNESCAPE_INPLACE= 1048576
;'escape #'s in paths
#URL_INTERNAL_PATH = 8388608
#URL_DONT_ESCAPE_EXTRA_INFO = 33554432
#URL_ESCAPE_SPACES_ONLY = 67108864
#URL_DONT_SIMPLIFY = 134217728
;Fake_addr.s= "http://vbnet.mvps.org/vbnet code lib/net code/ip address.htm"
Fake_addr.s="a-z A-Z 0-9 dürfen%nicht ersetzt werden!!!"
buff.s = EncodeUrl(Fake_addr)
Debug buff
Debug DecodeUrl(buff )
Procedure.s EncodeUrl(sUrl.s)
;'Converts unsafe characters,
;'such as spaces, into their
;'corresponding escape sequences.
;UrlEscapeW"
Protected dwSize.l,dwFlags.l
If Len(sUrl) > 0
*buff=AllocateMemory(#MAX_PATH)
dwSize = #MAX_PATH
dwFlags = #URL_DONT_SIMPLIFY
If OpenLibrary(#EncodeUrl,"shlwapi.dll")
If CallFunction(#EncodeUrl,"UrlEscapeW",sUrl,*buff,@dwSize,dwflags) = #ERROR_SUCCESS
ret.s = PeekS(*buff)
EndIf
EndIf
EndIf
CloseLibrary(#EncodeUrl)
FreeMemory(*buff)
ProcedureReturn ret
EndProcedure
Procedure.s DecodeUrl(sUrl.s)
;'Converts escape sequences back into
;'ordinary characters.
;UrlUnescapeW
Protected dwSize.l,dwFlags.l
If Len(sUrl) > 0
*buff=AllocateMemory(#MAX_PATH)
dwSize = #MAX_PATH
dwFlags = #URL_DONT_SIMPLIFY
If OpenLibrary(#UrlUnescape,"shlwapi.dll")
If CallFunction(#UrlUnescape,"UrlUnescapeW",sUrl,*buff,@dwSize,dwFlags) = #ERROR_SUCCESS
ret.s = PeekS(*buff)
EndIf
EndIf
EndIf
CloseLibrary(#UrlUnescape)
FreeMemory(*buff)
ProcedureReturn ret
EndProcedure
PB 5.10 Windows 7 x64