![]() |
Problem mit Indy und der Rapidshare-Api
Hallo Leute!
Ich arbeite zu Testzwecken derzeit an einer Implementierung der Rapidshare.com-Api für Premiumdownloads. Bisher klappt das auch alles ganz gut. Man kopiert sich die Links in die Zwischenablage, anschliessend werden sie automatisch gefiltert und alle relevanten Informationen dazu per Indy.get() downgeloaded (Prüfung des Dateistatus auf dem Server). Hier ist der Parser-Code:
Delphi-Quellcode:
Wie gesagt:
procedure TMainForm.parseLinks(x : String);
var y : String; i, j : Integer; errorCount : Integer; origList : TStringList; newList : TList; tmp, url, httpAnswer : String; newLink : TRSLink; inList : Boolean; begin // AUSLESEN DER LINKS origList := TStringList.Create; x := StringReplace(x, #13, ' ', [rfReplaceAll, rfIgnoreCase]); x := StringReplace(x, #10, '', [rfReplaceAll, rfIgnoreCase]); x := x + ' '; errorCount := 0; while(pos('rapidshare.com/files/', x) > 0) do begin x := copy(x, pos('rapidshare.com/files/', x), length(x)); tmp := copy(x, 0, pos(' ', x)- 1); origList.add(tmp); x := copy(x, length(tmp) + 1, length(x)); end; //origList.Delimiter := ' '; //origList.DelimitedText := x; newList := TList.Create; for i := 0 to origList.Count - 1 do begin x := origList.Strings[i]; newLink := TRSLink.create; newLink.URL := x; newList.Add(newLink); end; //////////////////////////////////////// // LINKS BEARBEITEN //////////////////////////////////////// for i := 0 to newList.Count - 1 do begin Application.ProcessMessages; newLink := TRSLink(newList.Items[i]); x := newLink.URL; x := copy(x, pos('//', x) + 2, length(x)); x := copy(x, pos('/', x) + 1, length(x)); x := copy(x, pos('/', x) + 1, length(x)); y := copy(x, pos('/', x) + 1, length(x)); x := copy(x, 0, pos('/', x) - 1); newLink.FileID := x; newLink.FileName := y; //////////////////////////////////////// // RS.COM API - HOSTNAMEN ABRUFEN //////////////////////////////////////// Application.ProcessMessages; URL := API_LINK + 'sub=checkfiles'; URL := URL + '&files=' + newLink.FileID; URL := URL + '&filenames=' + newLink.FileName; // Dateistatus abfragen... httpAnswer := ''; httpAnswer := idHTTP.Get(URL); // ... und verarbeiten if(pos('ERROR:', httpAnswer) < 1) then begin // SIZE IN BYTES httpAnswer := copy(httpAnswer, length(newLink.FileID) + length(newLink.FileName) + 3, length(httpAnswer)); newLink.SizeInBytes := StrToInt(copy(httpAnswer, 0, pos(',', httpAnswer) - 1)); // SERVER-ID httpAnswer := copy(httpAnswer, pos(',', httpAnswer) + 1, length(httpAnswer)); newLink.ServerID := copy(httpAnswer, 0, pos(',', httpAnswer) - 1); // STATUS httpAnswer := copy(httpAnswer, pos(',', httpAnswer) + 1, length(httpAnswer)); newLink.Status := StrToInt(copy(httpAnswer, 0, pos(',', httpAnswer) - 1)); // SHORT HOST httpAnswer := copy(httpAnswer, pos(',', httpAnswer) + 1, length(httpAnswer)); newLink.ShortHost := copy(httpAnswer, 0, pos(',', httpAnswer) - 1); // STATUS AUSGABE case newLink.Status of 0 : newLink.StatusStr := ARR_FileStatus[0]; 1 : newLink.StatusStr := ARR_FileStatus[1]; 3 : newLink.StatusStr := ARR_FileStatus[2]; 4 : newLink.StatusStr := ARR_FileStatus[3]; 5 : newLink.StatusStr := ARR_FileStatus[3]; 50..99 : newLink.StatusStr := ARR_FileStatus[1]; 100..200: newLink.StatusStr := ARR_FileStatus[1]; else newLink.StatusStr := ARR_FileStatus[5]; end; newLink.Percent := 0; end else begin inc(errorCount); end; L_Status.Caption := 'Status: getting Fileinfo... ' + IntToStr(i + 1) + ' / ' + IntToStr(newList.Count); L_Status.Caption := L_Status.Caption + ' - Errors: ' + IntToStr(errorCount); end; for i := 0 to newList.Count - 1 do begin newLink := TRSLink(newList.Items[i]); inList := false; for j := 0 to ARR_Links.Count - 1 do begin if(newLink.URL = TRSLink(ARR_Links.Items[j]).URL) then begin inList := true; break; end; end; if(inList = false) then begin ARR_Links.Add(TRSLink(newList.Items[i])); end; end; //////////////////////////////////////// // FREIGABE //////////////////////////////////////// newList.Free; origList.Free; end; Diese Prozedur scheint richtig zu arbeiten. Allerdings nur solange, wie man sich die Links direkt irgendwoher kopiert. Und jetzt zu meinem Problem: Da nur ein Rauskopieren der Links ziemlich wenig ist für ein Programm, habe ich eine Möglichkeit eingebaut um RSDF-Container Dateien zu laden. Um diese zu entschlüsseln schicke ich die RSDF-Datei per "Indy.Post()" an einen Server und verarbeite die Antwort des Servers. POST-Methode:
Delphi-Quellcode:
Das schicken der Datei klappt einwandfrei und die Links werden auch wirklich entschlüsselt in den String "httpAnswer" gespeichert.
procedure TMainform.DecryptRSDFFile();
var Stream : TIdMultiPartFormDataStream; httpAnswer, new : String; begin Stream := TIdMultiPartFormDataStream.Create; try try idHTTP.Request.ContentType := 'multipart/form-data'; Stream.AddFile('rsdffile', 'D:\test.rsdf', 'multipart/form-data'); httpAnswer := idHTTP.Post('http://wirpo032.bplaced.net/rsdf/rsdf_decrypt.php', Stream); sleep(5); except ShowMessage('Error parsing RSDF-File!'); end; httpAnswer := httpAnswer + #13; new := httpAnswer; new := copy(new, pos('<div id="links">', new) + length('<div id="links">'), length(new)); new := copy(new, 0, pos('</div>', new) - 1); new := StringReplace(new, chr(9), '', [rfReplaceAll]); new := StringReplace(new, ' ', '', [rfReplaceAll, rfIgnoreCase]); new := StringReplace(new, '<br><br>', '<br>', [rfReplaceAll, rfIgnoreCase]); new := StringReplace(new, '<br>', ' ', [rfReplaceAll, rfIgnoreCase]); new := StringReplace(new, #13#10, ' ', [rfReplaceAll, rfIgnoreCase]); new := StringReplace(new, #13, ' ', [rfReplaceAll, rfIgnoreCase]); new := StringReplace(new, #10, ' ', [rfReplaceAll, rfIgnoreCase]); new := copy(new, 6, length(new)); new := 'http' + new; parseLinks(new); finally Stream.Free; end; end; Allerdings kommt meine "parseLinks()"-Routine nicht mit dem Verarbeiten der Post-Antwort klar.. Es scheint so, als ob Indy noch Extrazeichen in die Antwort einbaut und diese mir alles zerschiessen... Konkret liegt das Problem irgendwo zwischen dem "Indy.Post()" und dem anschliessenden "Indy.Get()" in der Parse-Funktion.. Die Antwort der API in "parseLinks()" spuckt nämlich immer einen Errorstring aus, sobald ich die RSDF-Datei encrypte. Die Links an sich sind jedoch stets korrekt (URL-Variable). Dies konnte ich rausfinden, indem ich sie einfach kopiert habe und im Browser geöffnet habe.. Ich habe jetzt schon bald 2 Tage damit verbracht die Routinen neu zu schreiben, hab bis jetzt allerdings keine Lösung gefunden.. Ich hoffe ihr könnt mir dabei helfen! :-) |
AW: Problem mit Indy und der Rapidshare-Api
hast du schon einmal versucht zwischen dem Auswerten der entschlüsselten RSDF-Datei und dem Laden der Links dir die Ergebnisse anzuschauen? - Du vermutest jetzt, dass irgendwo ein Zeichen dazu kommt, welches du gar nicht haben willst. Schau doch einfach nach, ob da nicht gewollte Zeichen dabei sind und eliminiere sie dann.
Bernhard |
AW: Problem mit Indy und der Rapidshare-Api
Ich greif mal dieses Schnipsel aus deinem Code raus:
Delphi-Quellcode:
Deine Fehlerbehandlung ist total falsch.
try
idHTTP.Request.ContentType := 'multipart/form-data'; Stream.AddFile('rsdffile', 'D:\test.rsdf', 'multipart/form-data'); httpAnswer := idHTTP.Post('http://wirpo032.bplaced.net/rsdf/rsdf_decrypt.php', Stream); sleep(5); except ShowMessage('Error parsing RSDF-File!'); end; Ganz egal welcher Fehler auftritt (Server nicht erreichbar, keine Verbindung in Internet, Objekt(e) sind nil,Laufwerk D: nicht vorhanden, ...) es wird immer nur die gleiche nichtssagende Meldung angezeigt. Aber es kommt noch schlimmer: das Programm läuft weiter, obwohl die Eingabedaten fehlen. Da wäre es besser man hätte try...except ganz weggelassen. So sähe eine richtige Fehlerbehandlung aus:
Delphi-Quellcode:
try
url := 'http://wirpo032.bplaced.net/rsdf/rsdf_decrypt.php'; idHTTP.Request.ContentType := 'multipart/form-data'; Stream.AddFile('rsdffile', 'D:\test.rsdf', 'multipart/form-data'); httpAnswer := idHTTP.Post(url, Stream); sleep(5); except on E:Exception do begin E.Message := 'Error parsing RSDF-File!'#13#10+ url +#13#10 + E.Message; raise; end; end; |
AW: Problem mit Indy und der Rapidshare-Api
@sx:
Danke für die Hilfe! Ich hab Fehlerhandlungen bisher nie richtig gebraucht und wusste deshalb nicht genau, wie man sie einbaut. Habe das jetzt korrigiert. @rollstuhlfahrer: ja, das habe ich alles schon getan. Ich habe mir zur Hilfe mal die dekodierten Links in einem Memo anzeigen lassen. Sie sind auch wirklich korrekt! Als Beispiel: Ich kopiere z.B. folgenden Link im Browser: "http://www.rapidshare.com/12345678/testdatei.rar" Der Linkparser verarbeitet den Link korrekt und verarbeitet ihn in der API. Dies geschieht durch
Delphi-Quellcode:
Die Antwort der Api enthält dann alle wichtigen Daten für den Download, wie etwa Dateigröße, Server, usw..
Indy.get('http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=checkfiles&files=12345678&filenames=testdatei.rar');
So weit, so gut und bis hierhin alles korrekt (wie gesagt: kopieren geht). Entpacke ich nun einen RSDF-Container mit eben jenem Link, dann geschieht folgendes: Das "Indy.post()" wird abgesetzt und erhählt die HTML-Datei der Seite. In dem Beispiel folgendes:
Code:
Der Text wird verarbeitet und ich erhalte nur noch:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional //EN"
"http://www.art.org/TR/html4/loose.dtd"> <HTML> <HEAD> <title>Die entschlüsselten Links:</title> <link rel="stylesheet" href="css/style.css" type="text/css" /> <link rel="SHORTCUT ICON" href="img/PI.ico"> </HEAD> <BODY> <center><h1 id="logo"><img alt="Pi3625" src="img/logo.png" /></h1></center> <h1>Die entschlüsselten Links:</h1> <div id="links"> http://www.rapidshare.com/files/12345678/testdatei.rar<br><br> </div> <br><br> <h1>Noch einen RSDF Container online entschlüsseln?</h1> <form enctype="multipart/form-data" action="rsdf_decrypt.php" method="post"> <p>RSDF Datei: <input name="rsdffile" type="file"> <input type="submit" value="Hochladen"></p> </BODY> </HTML> "http://www.rapidshare.com/files/12345678/testdatei.rar " als String. Dieser String wird nun an parseLinks() weitergegeben und dort verarbeitet. Hier geschieht folgendes: Ich erzeuge durch die Verarbeitung wieder die nötigen Dinge für die API-Abfrage. Und erhalte (wie im ersten Beispiel)
Delphi-Quellcode:
Zumindest laut MeMo und ShowMessage. Allerdings gibt mir die API Diesmal einen Errorstring zurück. Und das scheint mir irgendwie seltsam.
Indy.get('http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=checkfiles&files=12345678&filenames=testdatei.rar');
Meine Vermutung ist daher, das sich irgendwo im String ein unsichtbares Zeichen (etwa der Art #13 oder #10) befindet und dadurch der Error hervorgerufen wird... Allerdings konnte ich bisher nichts finden. Und genau das ist mein Problem... Ich hoffe die Beschreibung hilft weiter! |
AW: Problem mit Indy und der Rapidshare-Api
So... ein wenig weiter bin ich nun gekommen.
Ich habe jetzt den "Indy.get" mal einfach durch ein URLDownloadToFile ersetzt und es ausprobiert.
Delphi-Quellcode:
Komischerweise funktioniert eben dieser Code, nicht jedoch der "Indy.get(URL)"...var myFile : TextFile; URL : String; PathToTempFile : String; httpAnswer : String; begin // Dateistatus abfragen... httpAnswer := ''; URLDownloadToFile(nil,PChar(URL),PChar(PathToTempFile),0,nil); AssignFile(myFile, PathToTempFile); Reset(myFile); while not Eof(myFile) do begin ReadLn(myFile, httpAnswer); end; closefile(myfile); end; Weiss da vielleicht jemand rat? Ich finde es eher unschön immer eine temporäre Datei zu erzeugen... |
AW: Problem mit Indy und der Rapidshare-Api
habs: du parst nicht richtig:
Delphi-Quellcode:
Wolltest du das <br> nicht weghaben? - Oder wolltest du das Leerzeichen jetzt doch wirklich haben?
new := StringReplace(new, '<br>', ' ', [rfReplaceAll, rfIgnoreCase]);
Bernhard |
AW: Problem mit Indy und der Rapidshare-Api
@Rollstuhlfahrer:
Das war schon so gewollt :-) Habe das zwar jetzt geändert, aber das hatte den einfachen Grund das man die Links viel einfacher mit einer Stringlist verwalten kann anschliessend.. Allerdings verstehe ich immernoch nicht so ganz, warum das alles mit Indy nicht funktioniert (bzw nicht richtig), jedoch mit URLDownloadToFile... :?: Habs jetzt vorerst so gelöst:
Delphi-Quellcode:
function TMainForm.myHTTPGet(const URL : String):String;
const Chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; var FileName : string; i, N: integer; TMPFilePath : String; myFile : TextFile; begin // ZUFÄLLIGER DATEINAME Randomize; FileName := ''; for i := 1 to 12 do begin N := Random(Length(Chars)) + 1; FileName := FileName + Chars[N]; end; // Datei resetten, falls vorhanden, sonst erstellen TMPFilePath := getTempDir + FileName + '.ttt'; AssignFile(myFile, TMPFilePath); Rewrite(myFile); closeFile(myFile); // RS-API Download URLDownloadToFile(nil,PChar(URL),PChar(TMPFilePath), 0, nil); // EINLESEN Reset(myFile); while not Eof(myFile) do begin ReadLn(myFile, Result); end; closeFile(myfile); // DATEI LÖSCHEN DeleteFile(TMPFilePath); end;
Delphi-Quellcode:
procedure TMainForm.parseLinks(x : String);
var y : String; i, j : Integer; errorCount : Integer; origList : TStringList; newList : TList; url, httpAnswer : String; nowLink : TRSLink; inList : Boolean; begin // AUSLESEN DER LINKS origList := TStringList.Create; x := StringReplace(x, #13, ' ', [rfReplaceAll, rfIgnoreCase]); x := StringReplace(x, #10, '', [rfReplaceAll, rfIgnoreCase]); x := x + ' '; errorCount := 0; origList.DelimitedText := x; for i := origList.Count - 1 downto 0 do begin if(pos('rapidshare.com/files/', origList.Strings[i]) < 1) then begin origList.Delete(i); end; end; newList := TList.Create; //////////////////////////////////////// // LINKS BEARBEITEN //////////////////////////////////////// for i := 0 to origList.Count - 1 do begin Application.ProcessMessages; nowLink := TRSLink.create; nowLink.URL := origList.Strings[i]; x := nowLink.URL; x := copy(x, pos('//', x) + 2, length(x)); x := copy(x, pos('/', x) + 1, length(x)); x := copy(x, pos('/', x) + 1, length(x)); y := copy(x, pos('/', x) + 1, length(x)); x := copy(x, 0, pos('/', x) - 1); nowLink.FileID := x; nowLink.FileName := y; //////////////////////////////////////// // RS.COM API - HOSTNAMEN ABRUFEN //////////////////////////////////////// Application.ProcessMessages; URL := API_LINK + 'sub=checkfiles'; URL := URL + '&files=' + nowLink.FileID; URL := URL + '&filenames=' + nowLink.FileName; // Dateistatus abfragen... httpAnswer := ''; httpAnswer := myHTTPGet(URL); // ... und verarbeiten if(pos('ERROR:', httpAnswer) < 1) then begin // SIZE IN BYTES httpAnswer := copy(httpAnswer, pos(',', httpAnswer) + 1, length(httpAnswer)); httpAnswer := copy(httpAnswer, pos(',', httpAnswer) + 1, length(httpAnswer)); nowlink.SizeInBytes := StrToInt(copy(httpAnswer, 0, pos(',', httpAnswer) - 1)); httpAnswer := copy(httpAnswer, pos(',', httpAnswer) + 1, length(httpAnswer)); // SERVER-ID nowlink.ServerID := copy(httpAnswer, 0, pos(',', httpAnswer) - 1); httpAnswer := copy(httpAnswer, pos(',', httpAnswer) + 1, length(httpAnswer)); // STATUS nowlink.Status := StrToInt(copy(httpAnswer, 0, pos(',', httpAnswer) - 1)); httpAnswer := copy(httpAnswer, pos(',', httpAnswer) + 1, length(httpAnswer)); // SHORT HOST nowlink.ShortHost := copy(httpAnswer, 0, pos(',', httpAnswer) - 1); // STATUS AUSGABE case nowlink.Status of 0 : nowlink.StatusStr := ARR_FileStatus[0]; 1 : nowlink.StatusStr := ARR_FileStatus[1]; 3 : nowlink.StatusStr := ARR_FileStatus[2]; 4 : nowlink.StatusStr := ARR_FileStatus[3]; 5 : nowlink.StatusStr := ARR_FileStatus[3]; 50..99 : nowlink.StatusStr := ARR_FileStatus[1]; 100..200: nowlink.StatusStr := ARR_FileStatus[1]; else nowlink.StatusStr := ARR_FileStatus[5]; end; nowlink.Percent := 0; newList.Add(nowLink); end else begin inc(errorCount); end; L_Status.Caption := 'Status: getting Fileinfo... ' + IntToStr(i + 1) + ' / ' + IntToStr(origList.Count); L_Status.Caption := L_Status.Caption + ' - Errors: ' + IntToStr(errorCount); end; for i := 0 to newList.Count - 1 do begin nowlink := TRSLink(newList.Items[i]); inList := false; for j := 0 to ARR_Links.Count - 1 do begin if(nowlink.URL = TRSLink(ARR_Links.Items[j]).URL) then begin inList := true; break; end; end; if(inList = false) then begin ARR_Links.Add(TRSLink(newList.Items[i])); end; end; //////////////////////////////////////// // FREIGABE //////////////////////////////////////// newList.Free; origList.Free; end;
Delphi-Quellcode:
Wenn jemandem noch eine Lösung zu dem Problem einfällt, dann darf er sich gerne melden :-)
procedure TMainform.DecryptRSDFFile(FilePath : String);
var Stream : TIdMultiPartFormDataStream; httpAnswer, new, url : String; begin Stream := TIdMultiPartFormDataStream.Create; try try URL := 'http://wirpo032.bplaced.net/rsdf/rsdf_decrypt.php'; idHTTP.Request.ContentType := 'multipart/form-data'; Stream.AddFile('rsdffile', FilePath, 'multipart/form-data'); httpAnswer := idHTTP.Post(URL, Stream); except on E:Exception do begin E.Message := 'Error parsing RSDF-File!' + #13#10 + URL + #13#10 + E.Message; raise; end; end; Application.ProcessMessages; httpAnswer := httpAnswer + #13; new := httpAnswer; new := StringReplace(new, '<br>', #13, [rfReplaceAll, rfIgnoreCase]); parseLinks(new); RefreshDLList(); finally Stream.Free; end; end; |
AW: Problem mit Indy und der Rapidshare-Api
Liste der Anhänge anzeigen (Anzahl: 1)
Hi,
bei URLDownloadToFile werden noch andere Werte bei Request gesetzt, die man bei Indy erst manuell setzen muss sprich der Rapidshare Server denkt, du bist ein Bot ;)
Delphi-Quellcode:
Außerdem würde ich immer noch den Request.Referer setzten.
with IdHTTP do
begin Request.Accept := 'text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1'; Request.AcceptCharSet := 'iso-8859-1, utf-8, utf-16, *;q=0.1'; Request.AcceptEncoding := 'deflate, gzip, identity, *;q=0'; Request.Connection := 'Keep-Alive'; Request.ContentType := 'application/x-www-form-urlencoded'; Request.UserAgent := 'Opera/9.80 (Windows NT 6.1; U; de) Presto/2.5.22 Version/10.51'; // Man kann auch den komischen Useragent mit F beginnend nehmen ... end; Ich habe im Anhang mal eine Klasse die von TIdHTTP abgeleitet wird und womit ich dann halt diese "Standardwerte" setzte, außerdem solche Spezialitäten wie CookieManager, gZIP, HTTP-Proxy, SOCKS und SSL... Weil wenn man mehrere Internetabfragen hat lohnt sich sowas :wink: Achja ich habe eine DLL zur Entschlüsselung von allen Containern, sowas würde ich nicht auf einen Server auslagern. Und ^^ du arbeitest die ganze Zeit mit copy um Informationen aus Strings zu Filter, dafür empfehle ich mit Regulären Ausdrücken zu arbeiten, einmal eingearbeitet und verstanden sparst du Lichtjahre :thumb: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:04 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz