Internet Highscore - Schnell und Einfach [NEU]

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Internet Highscore - Schnell und Einfach [NEU]

Beitrag von STARGÅTE »

Ich möchte hier mal ein Tutorial zum Thema "Einfache Internet HighScore, mit PB und PHP" aufmachen, weil ich gesehen habe das es viel Interesse dafür gibt.

Alle nachfolgenden CODEs dürfen in anderen Programmen/Spielen verwendet werden!


Voraussetzungen
Programmiersprachen: PB, PHP
Als erstes braucht man ein Webspace auf dem man php-Rechte hat um dort php-Codes abzulegen und eine Liste mit den HighScore Einträgen, welche die php-Datei verändern darf/kann.
Damit keine sich in die HighScore "reincheaten" kann, brauchen wir auf jeden Fall eine Art Kontroll-String der bei jedem Eintrag mitgesendet wird.


Vorbereitung
Wir legen uns also zu erst ein Ordner auf dem Webspace an (Ordner)


Webspace-Ordner

HighscoreList.php
Damit die Highscroe läuft brauchen wir am Anfang eine StartDatei (hier HighscoreList.php)

Code: Alles auswählen

<?php
$Item = array();
Diese Datei wird nun hochgeladen und mit vollen Schreibrechten versehen [Dateiattribut: 777]

Highscore.php
Diese Datei dient zum eintragen von Werten in die HighscoreList.php, und kontruliert vorher ob die Werte "echt sind" und schreibt dann die neue Zeile in die Liste.
Außerdem gibt sie (wenn gefordert) die Daten der Liste aus oder bei Fehler einen Fehlercode der dann von PB übersetzt wird.

Code: Alles auswählen

<?php

 // Diese Variable bitte selber den eigenen wünschen nach anpassen!
 //
 $HighScoreKey = 'Password';
 //


 // Sortierung nach Punkten
 function SortPoints($a,$b)
  {
  if     ($a[0]<$b[0]) return  1;
  elseif ($a[0]>$b[0]) return -1;
  else                 return  0;
  }


 // Neuer Highscore Eintrag
 if ($_GET['Points'])
  {
  $_GET['Name'] = urldecode($_GET['Name']);
  if (crypt($_GET['Points'].$_GET['Name'], $HighScoreKey) == $_GET['Key'])
   {
   include 'HighscoreList.php';
   foreach($Item as $Unit)
    {
    if ( ($Unit[0]==$_GET['Points']) and ($Unit[1]==$_GET['Name']) )
     {
     echo 'FALSE #3';
     exit;
     }
    }
   if ($File = @fopen('HighscoreList.php', 'a'))
    {
    // Eintrag in die Datei schreiben
    fwrite($File, '$Item[] = array('.$_GET['Points'].', "'.$_GET['Name'].'");'.chr(13));
    fclose($File);
    echo 'TRUE';
    }
   else
    {
    echo 'FALSE #2';
    }
   }
  else
   {
   echo 'FALSE #1';
   }
  }
 // Highscore auslesen
 else
  {
  include 'HighscoreList.php';
  usort($Item,SortPoints);
  if ($_GET['from']>0) $_GET['from']--;
  else                 $_GET['from']=0;
  if ($_GET['to']>0)   $_GET['to']--;
  else                 $_GET['to']=count($Item);
  for($n=$_GET['from'];$n<$_GET['to'];$n++)
   {
   // ausgabe der Highscore
   echo $Item[$n][0].chr(9).$Item[$n][1].chr(13);
   }
  }
  
?>
Diese Datei wird auch hochgeladen (normale Rechte)


PB-Code

HighScore
Nun folgen ein paar Proceduren zum auslesen/eintragen von/in HighScore-Einträgen:

Code: Alles auswählen


; Diese beiden Variablen bitte selber den eigenen wünschen nach anpassen!
; //
Global HighScoreKey$ = "Password"
Global HighScoreURL$ = "http://data.unionbytes.de/Highscore/Highscore.php"
; \\


InitNetwork()


; Lädt den Inhalt einer URL in einen String
Procedure.s DownloadToString(URL$, TimeOut=5000)
 Protected Event, Time, Size, String$
 Protected BufferSize = $1000
 Protected *Buffer = AllocateMemory(BufferSize)
 Protected ServerName$ = GetURLPart(URL$, #PB_URL_Site) 
 Protected ConnectionID = OpenNetworkConnection(ServerName$, 80) 
 If ConnectionID 
  SendNetworkString(ConnectionID, "GET "+URL$+" HTTP/1.0"+#LFCR$+#LFCR$) 
  Time = ElapsedMilliseconds()
  Repeat 
   Delay(10)
   Event = NetworkClientEvent(ConnectionID)
  Until Event Or ElapsedMilliseconds()-Time > TimeOut
  If Event
   Repeat
    Size = ReceiveNetworkData(ConnectionID, *Buffer, BufferSize) 
    String$ + PeekS(*Buffer, Size, #PB_Ascii) 
   Until Not Size
   Inhalt = FindString(String$, #LFCR$, 1)
   If Inhalt
    ProcedureReturn Mid(String$,Inhalt+3)
   Else
    ProcedureReturn String$
   EndIf
  EndIf
 EndIf 
EndProcedure


; Strukture der HighScore
Structure HighScore
 Points.l
 Name$
EndStructure
Global NewList HighScore.HighScore()


; Fügt einen Eintrag in die Internet HighScore
Procedure AddHighScoreItem(Points.l, Name$) 
 Protected Points$ = Str(Points) 
 Name$ = URLEncoder(Name$)
 Protected Get$ = "?Points="+Points$+"&Name="+Name$+"&Key="+DESFingerprint(Points$+Name$, HighScoreKey$)
 String$ = DownloadToString(HighScoreURL$+Get$)
 If String$
  If String$ = "TRUE"
   Debug "HighScoreEintrag hinzugefügt."
   ProcedureReturn #True
  ElseIf String$ = "FALSE #1"
   Debug "Ungültiger Eintrag!"
  ElseIf String$ = "FALSE #2"
   Debug "Fehler beim eintragen (bzw. schreiben in die Datei)!"
  ElseIf String$ = "FALSE #3"
   Debug "Identischer Eintrag!"
  Else
   Debug "Unbekannter Fehler!"
   Debug String$   
  EndIf
 Else
  Debug "Download fehlgeschlagen!"
 EndIf  
EndProcedure


; Lädt die Internet HighScore runter
;  Dabei kann ab einem bestimmten Platz (Start)
;  eine bestimmte Menge (Count) runtergeladen werden.
Procedure ExamineHighScore(Start=1, Count=0)
 Protected Get$, Position, OldPosition, Item$
 ClearList(HighScore())
 If Count > 0
  Get$ = "?from="+Str(Start)+"&to="+Str(Start+Count)
 Else
  Get$ = "?from="+Str(Start)
 EndIf
 String$ = DownloadToString(HighScoreURL$+Get$)
 If String$
  Repeat
   Position = FindString(String$, Chr(13), OldPosition+1)
   If Position
    Item$ = Mid(String$, OldPosition+1, Position-OldPosition-1)
    AddElement(HighScore())
    HighScore()\Points = Val(StringField(Item$, 1, Chr(9)))
    HighScore()\Name$ = StringField(Item$, 2, Chr(9))
    OldPosition = Position
   EndIf
  Until Not Position
  ResetList(HighScore())
  ProcedureReturn #True
 Else
  Debug "Download fehlgeschlagen!"  
 EndIf
EndProcedure

; Springt zum nächsten HighScore Eintrag (der Download-HighScore)
Macro NextHighScoreItem()
 NextElement(HighScore())
EndMacro

; Gibt die Punkte des HighScore Eintrags zurück
Macro GetHighScorePoints()
 HighScore()\Points
EndMacro

; Gibt den Namen des HighScore Eintrags zurück
Macro GetHighScoreName()
 HighScore()\Name$
EndMacro

Kommentar

In PB wird in AddHighScoreItem() eine URL erzeugt welche für php auslesbare Daten enthält.
Die Daten bestehen aus den Punkten und dem Namen.
Damit es keine unberechtigten Einträge gibt wird zusätzlich ein ÜberprüfungsString mitgesendet.
Dieser wird aus in PB mit DESFingerprint() erstellt und in php mit gesendetetn Daten und crypt().
Nur wenn beide Übereinstimmen, wird der Eintrag wirklich eingetragen.
Der Eigene SchlüsselString muss in PB und php identisch sein!
Um nun eine Spam zu verhindern (also mehrmals die gleiche URL aufrufen) werden nur Unterschiedliche Einträge hinzugefügt (also nur wenn Punkte oder Name unterschiedlich ist)
Fals während dieser Abläufe ein Fehler auftritt wird dieser von php übermittelt, und als DEBUG in PB ausgegeben bzw mit einem FALSE.
Um die Liste auslesen zu können wird ExamineHighScore() benötigt.
Dort kann wiederum ein Auslesestart angegeben werden und eine Anzahl an Einträgen die ausgelesen werden soll.
Das Abarbeiten dieser Einträge basiert dann auf einem ähnlichen System wie bei zB. ExamineDirectory.


Beispiel
Wer alle Werte so übernimmt wie ich sie gegeben habe kann hier dann schnell eine PB-Datei öffnen, die Proceduren übernehmen und dann diesen CODE ausfühen um zu sehen was passiert :
Liste Auslesen:

Code: Alles auswählen

ExamineHighScore()
While NextHighScoreItem()
 Debug Str(GetHighScorePoints())+"   "+GetHighScoreName()
Wend
Und wer sich auch verewigen möchte:

Code: Alles auswählen

Punkte = 123
Name$ = "Unbekannt"
Debug AddHighScoreItem(Punkte, Name$)

Schlusswort
Ich hoffe die CODEs sind verständlich, oder anwendbar, und ich hoffe ich habe euch damit viel geholfen.
Wer fragen hat, kann sie gerne stellen.
Zuletzt geändert von STARGÅTE am 09.07.2010 14:31, insgesamt 4-mal geändert.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
bluejoke
Beiträge: 1244
Registriert: 08.09.2004 16:33
Kontaktdaten:

Beitrag von bluejoke »

Ich hoffe bei deinem Spiel hast du andere Key-Werte verwendet als hier...

oh. Noch eins: Thnx for sharing!
Ich bin Ausländer - fast überall
Windows XP Pro SP2 - PB 4.00
Benutzeravatar
X0r
Beiträge: 2770
Registriert: 15.03.2007 21:47
Kontaktdaten:

Beitrag von X0r »

Ist das überhaupt sicher? Normalerweise prüft man in der PHP-Datei ein Passwort, welches auch noch gesendet wird.

Wenn das ganze nicht verschlüsselt abläuft, so kann man mit bestimmten Programmen einfach "die Links ablesen", die das Programm "aufruft".
Das wäre natürlich blöd.
Beispiel:
PHP_GetFunction("http://www.xyzsamplewebsite.com?passwor ... re="+score+"")


(Im Zweifelsfall hilft auch die ETNA DLL, die kann die Informationen verschlüsselt senden.)
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag von STARGÅTE »

genau das mache ich doch, ich sende zusätzlich eine Zeichenkette die mit MD5 und ein bisschen MOD verschlüsselt wurde.

Das machen beide Seiten (PB und PHP) und nur wenn beide Seiten gleich sind macht er den Eintrag.

Du kannst also gerne die php Seite aufrufen und Punkte=1000000&Name=Erster eitragen aber es wird nix pasieren
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
X0r
Beiträge: 2770
Registriert: 15.03.2007 21:47
Kontaktdaten:

Beitrag von X0r »

Wenn nichts pasieren wird, dann gute Arbeit! :mrgreen: :D
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag von Fluid Byte »

Ich werde demnächst eine Internet Highscore für meinen PureMemory Nachfolger benötigen aber ich frage mich wie sicher das hier ist. Wird die Sicherheit erhöht je länger $KeyWert1 und $KeyWert2 sind? Welche Möglichkeiten hat jemand der diesen Check umgehen will?

Falls ich diese Codes verwenden sollte wäre es außerdem gut wenn der API Kram durch PB Befehle ersetzt werden könnte. Denn soweit ich das sehe ist da nix dabei was nicht auch mit Onboard-Mitteln gehen würde.
Windows 10 Pro, 64-Bit / Outtakes | Derek
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7028
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag von STARGÅTE »

Die Sicherheitsfrage kann ich dir leider nicht beantworten...

den API-Kram kannst einfach rausschmeißen, und doch die PB-Proceduren ersetzten.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
AND51
Beiträge: 5220
Registriert: 01.10.2005 13:15

Beitrag von AND51 »

Fluid Byte hat geschrieben:Falls ich diese Codes verwenden sollte wäre es außerdem gut wenn der API Kram durch PB Befehle ersetzt werden könnte. Denn soweit ich das sehe ist da nix dabei was nicht auch mit Onboard-Mitteln gehen würde.
Dann tu es doch, wo ist das Problem???

Ersetze den OpenURL-Schmarrn doch einfach durch ReceiveHTTPFile(). Beim Überfliegen habe ich jetzt keine anderen API-Befehle mehr gesehen. Also müsst's das gewesen sein. :wink:
PB 4.30

Code: Alles auswählen

Macro Happy
 ;-)
EndMacro

Happy End
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag von Fluid Byte »

AND51 hat geschrieben:Dann tu es doch, wo ist das Problem???
Ist zwar schon 'ne Weile her aber trotzdem, ein Fragezeichen reicht.

Aber nun zur durchaus berechtigten Frage des Problems ...

Wie gesagt, ich habe den Code überflogen und da es sah so aus als würde es mit Onboard-Befehlen funktionieren. Man muss aber mit ReceiveHTTPFile() die empfangenen Dateien temoprär auf Pladde speichern. Das eigentliche Problem ist aber das ReceiveHTTPFile() nur mit reinen HTML Dateien zu funktionieren scheint bzw. verbuggt ist:

http://www.purebasic.fr/english/viewtopic.php?t=32657

@stargäht:
Gibt es einen besonderen Grund warum du für Modulo dein eigenes Süppchen kochst anstatt den % Operator zu nutzen?

Außerdem denke ich das die URL's verschlüsselt werden müssten da es sonst leicht zu manipulieren wäre. Ich beziehe mich hierbei auf diese Zeile:

Code: Alles auswählen

Ergebnis$ = OpenURL(URLPath$ + "eintrag.php?Punkte=" + Punkte$ + "&Name=" + Name$ + "&Check=" + Check$)
Ich bin kein Experte aber ich denke es sollte nicht all zu schwer sein die Anwendung mit OllyDbg zu laden, den String zu suchen und an entsprechender Stelle seinen eigenen Highscorewert zu setzen.
Windows 10 Pro, 64-Bit / Outtakes | Derek
Benutzeravatar
X360 Andy
Beiträge: 1206
Registriert: 11.05.2008 00:22
Wohnort: Bodensee
Kontaktdaten:

Beitrag von X360 Andy »

Ich habe ein kleines Problem es wird mir bei "Liste" (auf meinem Webspace) nichts angezeigt ...

Hab mir die 3 datein erstellt und auf meinem Webspace geladen ( Liste.txt Liste.php und Eintag.php ) hab den Datein die CHMOD Rechte 0777/777 geben.
Hab dann einfach alle PB Codes kopiert... ( hab URL Path geändert auf meine "Meine seite.de/HighScore/ )

Hab dann einfach mal 1000 Punkte und meinen Name eingeben und ne Exe. erstellt , aber es kommt nichts an ( also die Liste.txt wird nicht erweitert )

Vie. kann mir jemand sagen was ich Falsch mache , muss ich noch mehr am Code ändern ? ( hab ihn mehrmals geändert , wüsste aber nicht was ich noch an "mich" anpassen sollte/müsste)



Mfg

P.s hab PB 4.20 Vista und Webspace auf Lima-City

http://andreas-rauscher.lima-city.de/HighScore/ // Keys habe ich geändert (-;
Antworten