ich brauchte die Möglichkeit eine Webseite im Standardbrowser aufzurufen und dieser Daten per POST mitzugeben. Da man die Daten nicht einfach an die URL anhängen kann und damit den Standardbrowser mit Runprogram() aufrufen kann, musste ich eine Zwischenschicht bauen, die ich mir ein wenig von Dropbox abgeschaut habe.
Im Grunde wird eine temporäre HTML-Datei erstellt, die die zu übergebenden Daten verschlüsselt enthält und nach dem Entschlüsseln an die eigentliche Webseite weitergibt, indem sie eine HTML-Form submitted. Der Schlüssel zum Entschlüsseln wird als Hash am Ende der URL übergeben und während der Skriptausführung entfernt, sodass in der Browser-History keine Rückstände bleiben.
Damit der Purebasic-Code möglichst kompakt bleibt, habe ich das Template der HTML-Datei möglichst klein gehalten, d.h. auch den JS-Code minimiert.
Um den Code direkt testen zu können, habe ich ein kleines Skript auf meinem Webspace liegen, dass POST- und GET-Daten anzeigt. Hier nun der Code:
Aktuell Windows/Linux only und PB 5.41 beta 2
Code: Alles auswählen
EnableExplicit
DeclareModule BrowserPost
EnableExplicit
Declare.i openURL(actionUrl.s, Map postData.s(), title.s = "", nojsUrl.s = "", nojsInfo.s = "", keyLength.i = 64)
Declare.i removeTempFiles(deltaTime.i = -1)
EndDeclareModule
Module BrowserPost
EnableExplicit
Structure TFiles
time.i
file.s
EndStructure
Global NewList tFiles.TFiles()
Global tfilesLock.i = CreateMutex()
; Konvertiert text.s zu Unicode, verschlüsselt die Rohdaten mit dem Schlüssel und
; konvertiert die Daten zu einem Hex-String.
Procedure.s convert2Hex(text.s, *key, keyLength.i, *length.Integer = 0)
Protected dataSize.i = StringByteLength(text, #PB_Unicode) + SizeOf(Unicode)
Protected *buffer = AllocateMemory(dataSize)
PokeS(*buffer, text, -1, #PB_Unicode)
Protected hex.s = "", *i.Unicode = *buffer, *k.Unicode = *key
While *i\u
hex + RSet(Hex(*i\u ! *k\u, #PB_Unicode), 4, "0")
*i + SizeOf(Unicode)
*k + SizeOf(Unicode)
If (*k - *key) >= keyLength
*k - keyLength
EndIf
Wend
FreeMemory(*buffer)
If *length
*length\i = dataSize - SizeOf(Unicode)
EndIf
ProcedureReturn hex
EndProcedure
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
; ts-soft: http://www.purebasic.fr/german/viewtopic.php?p=282092#p282092
Procedure.s FindAssociatedProgram(File.s)
Protected Result.s = Space(#MAX_PATH)
Protected Error
Error = FindExecutable_(@File, 0, @Result)
If Error <= 32
ProcedureReturn ""
EndIf
ProcedureReturn Result
EndProcedure
CompilerElse
Procedure.s FindAssociatedProgram(File.s)
ProcedureReturn "x-www-browser"
EndProcedure
CompilerEndIf
Procedure openURL(actionUrl.s, Map postData.s(), title.s = "", nojsUrl.s = "", nojsInfo.s = "", keyLength.i = 64)
If Not (keyLength % 2 = 0)
ProcedureReturn #False
EndIf
; Erzeuge Schlüssel
Protected *key = AllocateMemory(keyLength)
If Not *key
ProcedureReturn #False
EndIf
If Not OpenCryptRandom()
ProcedureReturn #False
EndIf
CryptRandomData(*key, keyLength)
Protected i.i, hexKey.s = ""
For i = 0 To keyLength - 1 Step 2
hexKey + RSet(Hex(PeekU(*key + i), #PB_Unicode), 4, "0")
Next
; Wandle Post Data in JSON-String um.
Protected json.i = CreateJSON(#PB_Any)
Protected jsonData.i = SetJSONObject(JSONValue(json))
ForEach postData()
SetJSONString(AddJSONMember(jsonData, MapKey(postData())), postData())
Next
Protected jsonStr.s = ComposeJSON(json)
FreeJSON(json)
; Wandle JSON-String in Hex-String um.
Protected jsonLength.i, jsonHex.s = convert2Hex(jsonStr, *key, keyLength, @jsonLength)
; Wandle Länge des JSON-String in HEX um.
Protected.s hexLength = RSet(Hex(jsonLength * 2, #PB_Long), 8, "0")
; Gib Schlüssel wieder frei
FillMemory(*key, keyLength, 0)
FreeMemory(*key)
; Erstelle Mark of the Web
Protected motw.s = GetURLPart(actionUrl, #PB_URL_Protocol) + "://" + GetURLPart(actionUrl, #PB_URL_Site)
; Lies HTML-Template aus Datasection aus.
Protected template.s = PeekS(?template_begin2, -1, #PB_Unicode) ;PeekS(?template_begin, -1, #PB_UTF8)
; Ersetze Variablen in Template.
template = ReplaceString(template, "%MOTW%", "(" + RSet(Str(Len(motw)), 4, "0") + ")" + motw)
template = ReplaceString(template, "%TITLE%", title)
template = ReplaceString(template, "%ACTION%", actionUrl)
template = ReplaceString(template, "%POSTDATA%", jsonHex)
template = ReplaceString(template, "%NOJSACTION%", nojsUrl)
template = ReplaceString(template, "%NOJSINFO%", nojsinfo)
; Suche zufälligen nicht existenten Dateinamen im temporären Verzeichnis
Repeat
Protected tempFile.s = GetTemporaryDirectory() + "_post" + Hex(Random(2147483647), #PB_Long) + "-" + Hex(Random(2147483647), #PB_Long) + ".html"
Until FileSize(tempFile) = -1
; Schreibe Template in Datei
Protected fileId.i = CreateFile(#PB_Any, tempFile)
If Not fileId
ProcedureReturn #False
EndIf
WriteString(fileId, template, #PB_UTF8)
CloseFile(fileId)
LockMutex(tfilesLock)
If AddElement(tFiles())
tFiles()\file = tempFile
tfiles()\time = Date()
EndIf
UnlockMutex(tfilesLock)
; Suche Standardprogramm zum Öffnen von HTML-Dateien.
Protected browser.s = FindAssociatedProgram(tempFile)
If browser = ""
ProcedureReturn #False
EndIf
; Setze URL für den Browser zusammen
Protected call.s = ~"\"file://" + tempFile + "#" + hexLength + hexKey + #DQUOTE$
ProcedureReturn RunProgram(browser, call, "")
DataSection
template_begin:
;IncludeBinary "OpenBrowserWithPostData.html"
;Data.u 0
template_begin2:
Data.s ~"<!DOCTYPE html>\r\n<!-- saved from url=%MOTW% -->\r\n<html><head>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">" +
~"<script type=\"text/javascript\">\r\n" +
"!function(){'use strict';function t(t,e){if(void 0==t||void 0==e||t.length%4!==0||e.length%4!==0||t.length<12)return null;" +
"var n=parseInt(t.slice(0,8),16);if(n!==e.length)return null;t=t.substr(8);for(var r=0,i='',o=0;o!==e.length;o+=4)i+=String." +
"fromCharCode(parseInt(t.slice(r,r+4),16)^parseInt(e.slice(o,o+4),16)),r=(r+4)%t.length;return i}function e(){var e=window." +
"location.hash.substr(1);window.location.hash='';var n=document.getElementsByName('data')[0],r=t(e,n.getAttribute('post-data'));" +
"if(document.submitPost.removeChild(n),null!=r){var i=JSON.parse(r);for(var o in i)if(i.hasOwnProperty(o)){var s=document." +
"createElement('input');s.setAttribute('type','hidden'),s.setAttribute('name',o),s.setAttribute('value',i[o]),document.submitPost." +
~"appendChild(s)}document.submitPost.submit()}}window.onload=e}();\r\n" +
"</script><title>%TITLE%</title></head><body><form id='submitPost' name='submitPost' action='%ACTION%' method='post'>" +
"<input type='hidden' name='data' value='' post-Data='%POSTDATA%'><noscript><div class='center'>" +
~"<meta id=\"meta-refresh\" http-equiv=\"refresh\" content=\"2;URL=%NOJSACTION%\"><p>%NOJSINFO%</p>" +
~"<a href=\"%NOJSACTION%\">Link</a></div></noscript></form></body></html>"
Data.u 0
EndDataSection
EndProcedure
Procedure.i removeTempFiles(deltaTime.i = -1)
If deltaTime < 0
ProcedureReturn ListSize(tFiles())
EndIf
LockMutex(tfilesLock)
ResetList(tFiles())
While NextElement(tFiles())
If tFiles()\time + deltaTime <= Date()
DeleteFile(tFiles()\file)
DeleteElement(tFiles())
EndIf
Wend
UnlockMutex(tfilesLock)
ProcedureReturn ListSize(tFiles())
EndProcedure
EndModule
NewMap postData.s()
postData("__ac_name") = "admin"
postData("__ac_password") = "herein"
postData("form.submitted") = "1"
postData("pwd_empty") = "0"
postData("js_enabled") = "0"
BrowserPost::openURL("http://freakscorner.de/test.php?bla=normales+GET", postData(), "Bastelkeller Weiterleitung", "http://freakscorner.de/", "Da in ihrem Browser Skripte deaktiviert wurden, können die Daten nicht automatisch übertragen werden.")
Delay(5000)
BrowserPost::removeTempFiles(0)
- Mac-Version
- Automatisches Löschen der temporären Datei nach einer bestimmten Zeit.
Code: Alles auswählen
<html>
<body>
<h3>POST</h3>
<? var_dump($_POST); ?>
<h3>GET</h3>
<? var_dump($_GET); ?>
<h3>REQUEST</h3>
<? var_dump($_REQUEST); ?>
</body>
</html>
Code: Alles auswählen
<!DOCTYPE html>
<!-- saved from url=%MOTW% -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript">
(function () {
"use strict";
function decryptData(key, data) {
if (key == undefined || data == undefined || (key.length % 4) !== 0 || (data.length % 4) !== 0 || key.length < 12) {
return null;
}
var dataLength = parseInt(key.slice(0, 8), 16);
if (dataLength !== data.length) {
return null;
}
key = key.substr(8);
var j = 0, out = '';
for (var i = 0; i !== data.length; i += 4) {
out += String.fromCharCode(parseInt(key.slice(j, j + 4), 16) ^ parseInt(data.slice(i, i + 4), 16));
j = (j + 4) % key.length;
}
return out;
}
function go() {
var hashKey = window.location.hash.substr(1);
window.location.hash = '';
var inputs = document.getElementsByName('data')[0];
var jsonStr = decryptData(hashKey, inputs.getAttribute('post-data'));
document.submitPost.removeChild(inputs);
if (jsonStr == null) {
return;
}
var jsonObj = JSON.parse(jsonStr);
for (var key in jsonObj) {
if (jsonObj.hasOwnProperty(key)) {
var hiddenInput = document.createElement("input");
hiddenInput.setAttribute("type", "hidden");
hiddenInput.setAttribute("name", key);
hiddenInput.setAttribute("value", jsonObj[key]);
document.submitPost.appendChild(hiddenInput);
}
}
document.submitPost.submit();
}
window.onload = go;
})();
</script>
<title>%TITLE%</title>
</head>
<body>
<form id="submitPost" name="submitPost" action="%ACTION%" method="post">
<input type="hidden" name="data" value="" post-data="%POSTDATA%">
<noscript>
<div class="center">
<meta id="meta-refresh" http-equiv="refresh" content="2;URL=%NOJSACTION%">
<p>%NOJSINFO%</p>
<a href="%NOJSACTION%">Link</a>
</div>
</noscript>
</form>
</body>
</html>
- Linux-Version hinzugefügt
- In Modul gepackt
- Löschmöglichkeit eingebaut.