Aller au contenu
Concours du mois de Juin 2018 : Carte Amazon 15 €

Akihira

Membre
  • Compteur de contenus

    23
  • Inscription

  • Dernière visite

  • Jours gagnés

    7
  • Points

    24 [ Donner ]

Akihira a gagné pour la dernière fois le 6 mars

Akihira a eu le contenu le plus aimé !

Réputation sur la communauté

14 Apprenti

À propos de Akihira

  • Rang
    Moussaillon
  • Date de naissance 14 juin

Profil

  • Discord
    Inconnu
  • Skype
    Inconnu
  • Nationalité
    Français
  • Sexe
    Femme

Visiteurs récents du profil

273 visualisations du profil
  1. partage VDI FILES 2016 FE (optimisé)

    Merci. On voit un gros partage, il reste des problèmes, très mineurs et facilement corrigés en cherchant un peu sur internet. Bonne initiative, merci !
  2. partage Choix de skin pour magasin

    Pas mal pas mal !
  3. Tu aurais pu donner la méthode pour se connecter par socket au passage. $d = NEW PDO('mysql:unix_socket=/tmp/mysql.sock;dbname='.$str, $str, $str);
  4. On verra ça plus tard, pour l'instant je n'ai pas le temps. Tu pourrais continuer non ? Je ne pense pas t'avoir perdu à ce niveau là
  5. partage Protéger un peu son client

    3 ans ? Ah. Je suis à la bourre on dirait !
  6. partage Protéger un peu son client

    Je n'utilise plus là LZO, c'est trop obsolète, je te laisse le constater ici d'ailleurs : Contenu Masqué Tu as du choix, LZ4, etc... De plus j'ai réuni mes eix et epk dans un même fichier. J'ai également changé tout le système de cryptage, voilà pourquoi je n'ai plus ses parties de client, j'ai c/c d'un autre forum le code je ne sais plus le quel. Oupss j'ai du passé à côté alors ?! Sans problème !
  7. partage Protéger un peu son client

    C'est justement car il est partagé que j'ai pas tout traduit, et que j'ai laissé "lista" etc... @Takuma C'est assez compliqué pour moi de ce côté, je suis plus en LZO comme la plus part du temps, et clairement j'ai pas le courage de retourner sous LZO juste pour ça. J'étais entrain d'y penser, je pourrais limite faire un tuto pour forcer le démarrage du client par le launcher, grâce à des arguments et le lanceur en ressources du launcher. Je me vois pas de recoder un launcher entier et recoder l'UserInterface pour qu'il ne se lance qu'à ce moment, etc... J'ai carrément la flemme ! Merci
  8. partage Protéger un peu son client

    Bonjour. On dit toujours que la protection ne doit pas être exclusive... Elle l'est souvent. Je n'ai pas des grosses connaissances en ce sujet, je ne joue pas souvent à Metin2, j'ai juste regardé une après midi les sources et comment est fait le client, pour essayer de faire une protection basique, dont le contenu est compréhensible par tout le monde afin de faire progresser les personnes avec des connaissances assez modestes comme les miennes. Je suis pas codeuse, je ne travaille pas là de dans, mon code n'est peut-être pas très optimisé, si vous faites mieux allez-y, ça me fera plaisir de voir comment j'aurai pu faire autrement Avant n'importe quelle manipulation se trouvant dans ce tutoriel, vous devez faire une sauvegarde. Ne vous dites pas "je vais suivre à la lettre c'est bon". Je n'ai pas du tout envie que vous soyez obligé de recommencer quelques choses car je me suis mal exprimée. L'avertissement étant donné, nous pouvons commencer. Vérification de certains fichiers par les sources client : Nous allons ici utiliser l'encodage MD5. Je sais que des collisions sont possibles, et que je devrais utiliser le sha-256. Mais je considère que le risque de collision entre deux fichiers sachant qu'un doit avoir plus de contenu tout en restant fonctionnel... Je considère que la probabilité est nulle. Bien, commencer, vous allez devoir ajouter un fichier dans votre UserInterface, pour cela vous avez plusieurs méthodes, la plus simple reste encore (à mon goût) celle-ci : Vous allez ensuite nommé ce fichier comme bon vous semble, mais je vous conseil de l'appelé mh5.h comme ça, pas de confusion possible. Vous allez ensuite copier l'intégralité de ceci dans le fichier : Contenu Masqué Vous pouvez ensuite sauvegarder votre fichier. Ouvrez ensuite votre Locale_inc.h : Ajoutez en dehors de toute boucle : #define ENABLE_CHECK_FILES_MD5 Je vous explique ceci à la fin, c'est très simple à comprendre vous allez voir, je vous mettrai une petite note explicative. Ensuite, rendez-vous dans votre UserInterface.cpp : Ajoutez avec les autres includes : #ifdef ENABLE_CHECK_FILES_MD5 #include md5.h #include windows.h #endif Ici, nous ajoutons des fichiers nécessaire au script. On inclue les données de ce fichier dans UserInterface.cpp. Cherchez ensuite : static const char * sc_apszPythonLibraryFilenames[] = Vous trouverez normalement une liste qui ressemble à celle-ci : static const char * sc_apszPythonLibraryFilenames[] = { "UserDict.pyc", "__future__.pyc", "copy_reg.pyc", "linecache.pyc", "ntpath.pyc", "os.pyc", "site.pyc", "stat.pyc", "string.pyc", "traceback.pyc", "types.pyc", "\n", }; Vous allez ajouter en bas : #ifdef ENABLE_CHECK_FILES_MD5 #define MAX_ROWS_MD5 21 static char * ar_szMD5FileNames[MAX_ROWS_MD5][2] = { { "lib/__future__.pyc", "d2505c6e64dc44a1745dda0905f4e787" }, { "lib/copy_reg.pyc", "5e996d35b598676b253dd25fa3809ef2" }, { "miles/mssdsp.flt", "cb71b1791009eca618e9b1ad4baa4fa9" }, { "miles/msssoft.m3d", "bdc9ad58ade17dbd939522eee447416f" }, { "miles/mssa3d.m3d", "e089ce52b0617a6530069f22e0bdba2a" }, { "miles/mss32.dll", "6400e224b8b44ece59a992e6d8233719" }, { "pack/uiscript.eix", "d211c0a83ff2c771946d73554916bd9a" }, { "python27.dll", "d219c0a8aff2c771946d73554916bd9a" } }; #endif Vous allez ici devoir ici déjà : Mettre les fichiers que vous désirez, Ajouter une virgule à toutes les lignes sauf à la dernière Changer les hash md5 "d2505c6e64dc44a1745dda0905f4e787" selon vos fichiers. Faites bien attention à ajouter la destination dans le nom de fichier, par exemple pour les packs vous voyez bien que j'ai ajouté pack/uiscript.eix car mes packs se trouvent dans le dossier packs. Pour hash vos fichiers, je ne vous laisse pas dans la nature, voici un petit programme que j'ai recodé de façon à pouvoir vos permettre de : Voir le MD5 de vos fichiers Changer le hash md5. En voici donc une release : Contenu Masqué Vous allez ensuite chercher : bool __IsLocaleVersion(LPSTR lpCmdLine) { return (strcmp(lpCmdLine, "--perforce-revision") == 0); } Puis ajouter en dessous : #ifdef ENABLE_CHECK_FILES_MD5 void CheckMD5Filenames() { MD5 md5; for (int it = 0; it < _countof(ar_szMD5FileNames); it++) { if (strcmp(md5.digestFile(ar_szMD5FileNames[it][0]), ar_szMD5FileNames[it][1])) { char szBuf[512 + 1]; snprintf(szBuf, sizeof(szBuf), "Le fichier %s est corrumpu.", ar_szMD5FileNames[it][0]); MessageBoxA(NULL, szBuf, "#Metin2", NULL); exit(0); } } } #endif Enfin, cherchez : if (strstr(lpCmdLine, "--hackshield") != 0) return 0; Ajoutez après : #ifdef ENABLE_CHECK_FILES_MD5 CheckMD5Filenames(); #endif Félicitations ! Vous n'avez plus qu'à compiler vos sources à nouveau. Petite explication sur le code : Nous allons maintenant voir comment exécuter un scripte de sécurité en Python. Trois problèmes se posent à nous : Que faire ? Comment le faire ? Où le faire ? Nous allons commençons par le plus simple "Où ?" : Et bien, sachant qu'en Python, le premier fichier chargé est le system.py cependant... Il ne dispose pas encore à ce stade de toutes les fonctions dont nous allons avoir besoin, nous allons par conséquence prendre le deuxième fichier : prototype.py Vous allez donc mettre en toute première ligne de ce fichier : import akihira Note : Remplacez akihira par ce que vous voulez. Vous allez ensuite créer un fichier du même nom que celui que vous avez importer dans notre root, par exemple ici, akihira.py. Bien, commençons à éditer notre fichier. Vous allez commençons par ajouter ces imports : import os import thread import time import app import dbg os : Il va nous permettre de nous balader dans les destinations et d'utiliser les fichiers. thread : Il va nous permettre quant à lui de créer des instances, et donc de faire plusieurs choses en même temps. time : Il va bien falloir donner une fréquence à la répétition de la vérification, la voici. app : C'est un module généré par C++ dans les sources client. Nous allons ici nous en servir pour "faire planter" le client. dbg : DialogBoxGenerator, il me semble... Il permet de créer des boites de dialogue, ici il nous servira pour des fenêtres d'erreur. Bien, nous allons d'abord créer une liste, dans celle-ci, nous allons écrire la liste des programmes "parasites". C'est à dire ceux que nous ne voulons pas. Pour créer une liste en python, rien de plus simple ! Nous allons aimer ça syntaxe simple : black_list = [] Votre liste est crée... Je vous l'accorde, il faut la remplir ! Pour cela nous allons ajouter le nom des programmes en tant que chaine de caractère, donc entre guillemet(/apostrophe) et les séparer entre eux par une virgule. Voici un exemple : black_List = ["injector.exe","cheatengine-x86_64.exe"] Bien, je vous laisserai remplir la liste comme vous le souhaitez, de toute façon, nous allons adapter notre code pour qu'il s'adapte à n'importe quelle liste. Nous allons ensuite devoir dire à notre programme : Pour chaque membre de la liste (que l'on va nommé "membre") : Récupère la liste des programmes. Si un deux est le même que 'membre' Tu fermes le client Sinon : Tu recommences Nous n'allons en fait pas exactement respecter cette architecture, nous allons mettre exactement : Répète à l'infini : Pour chaque processus 'p' du gestionnaire de tâche : Pour chaque membre de la liste Si dans le processus tu trouves "membre": On arrête le processus On attend 5 secondes Bon est bien... On a du pain sur la planche ! Pour répéter à l'infini, nous allons utiliser une évidence. Mais d'abord, nous allons contenir tout ça dans une fonction afin de pouvoir la démarrer en tant qu'instance (thread) : def __process(): pass Bien, je vous ai parlé d'une évidence, vous vous demandez peut être ce que c'est, et bien... si je vous dis que 1 est égale à 1, vous me dit quoi ? "Bah oui" Et bien voilà, on va dire à Python : "Le temps que 1 = 1 :" Nous utilisons pour ça la structure while. Cela donne : def __process(): while 1 ==1: pass Bien... Continuons ! '¨pour chaque processus... Vous ne pouvez pas deviner ceci si vous débutez, je vous le donne : def __process(): while 1 == 1: for p in os.popen("tasklist"): Bien, ensuite "Pour chaque membre de la liste : def __process(): while 1 == 1: for p in os.popen("tasklist"): for Member in black_List: "Si tu trouves de dans "Member" : def __process(): while 1 == 1: for p in os.popen("tasklist"): for Member in black_List: if process.find(Member) !=1: Nous allons ensuite écrire ceci, je vous explique après : def __process(): try: while 1 == 1: for p in os.popen("tasklist"): for Member in black_List: if process.find(Member) !=1: p = process.slip() os.popen("taskkill /im %s /f" %p[0]) time.sleep(5) except: time.sleep(5) "MAIS T'AS TOUT CHANGÉ ÇA VA PAS DANS TA TÊTE ?" Mais nous, résumons, qu'est-ce que j'ai fais ? j'ai entouré le code de : try: Traduction : Essaye de... except : Traduction : Si tu n'y arrives pas : S'il n'y arrive pas, je lui ai dis ici d'attendre 5 secondes. J'ai ensuite rajouté le fait de lancer une commande pour "tuer"/arrêter le processus, puis attendre 5 secondes. Bien, il ne nous reste plus qu'une chose à faire ! Lancer la fonction grâce à une instance(thread), pour cela je vous donne la façon de faire : thread.start_new_thread(__process, ()) Mettez ceci à la fin de votre fichier, sans aucune tabulation. Félicitations ! Vous avez maintenant une boucle qui scanne les processus en permanence ! Vous devenez un champion ! Bien, maintenant nous allons faire la même chose pour chaque fichier du client avec des extensions et une liste, vous avez compris le principe, je peux vous donner directement la boucle : BanExt = [".m3d", ".py", ".fld", ".mix", ".asi"] Dest = os.listdir('.') Dest.sort() for Member in BanExt: for File in Dest: if File.find(Member) != -1: dbg.LogBox("Une erreur est survenue: " + str(File) + "") try: os.remove(File) except: dbg.LogBox("Erreur !") dbg.LogBox("Fichier: " + str(File)) app.Abort() A vous de choisir, si vous voulez refaire une boucle avec une évidence et une instance, pour lancer ce scan en permanence. Nous repassons du côté de vos sources clients pour la suite, ne vous faites pas avoir ! Bien, nous allons maintenant ajouter une protection très simple, le principe est aussi très simple : Quand un joueur attaque : Si il n'attaque pas (c'est assez contradictoire je sais) On annule l'action. Pour cela, nous allons juste ajouter deux minables lignes dans le PythonNetworkStreamPhaseGame.cpp Cherchez : TPacketCGAttack kPacketAtk; Ajoutez juste en dessous : if (!__IsPlayerAttacking()) return true; Nous vérifions ici que le joueur est bien entrain d'attaquer. Cette modification est réservée aux personnes ayant un minimum de connaissance en Python. Nous allons maintenant changer le premier fichier Python chargé afin de pouvoir gérer au maximum les erreurs en cas de besoin : Rendez-vous dans UserInterface.cpp : if (!pyLauncher.RunFile("system.py")) Changez comme vous le souhaitez le nom, et vous pouvez commencer à taper des scripts avant de lancer véritablement le client. Vous pouvez dans le même fichier changer le premier pack chargé afin de perturber les nouveaux apprentis pirates : Toujours dans UserInterface.cpp : CEterPackManager::Instance().RegisterRootPack((stFolder + std::string("root")).c_str()); Modifier vos clés de compressions : Cette manipulation s'adresse aux personnes n'ayant pas changer leur compression et fonctionnant toujours sous LZO. Dans vos sources clients, rendez-vous dans Eterpack.cpp : Vous trouverez : static DWORD s_adwEterPackKey[] = { 45129401, 92367215, 681285731, 1710201, }; static DWORD s_adwEterPackSecurityKey[] = { 78952482, 527348324, 1632942, 486274726, }; Vous pourrez ensuite les modifications comme bon vous sembles le temps que vous pouvez les convertir en hexadécimal grâce à un petit script python disponible ici : import struct print "Exemple de clé: b99eb0026f69810563989b2879181a00\n" string=raw_input("Clé héxadécimal: ") lista=struct.unpack("LLLL", string.decode('hex')) n=0 print "\nGenerateur: \n" for i in lista: n+=1 i=str(i) i=i.replace("L", "") print "A" + str(n) + " = " + i Vous devrez ensuite entrées ces valeurs dans votre packer afin de l'adapté. Vous devrez ensuite repacker tout vos packs avec la nouvelle compression ! Changer les extensions de vos packs : Vous pouvez effectivement changer les extensions de vos packs grâce à une méthode très simple. Rendez vous dans Eterpack.cpp : strncpy(m_indexFileName, dbname, MAX_PATH); strcat(m_indexFileName, ".eix"); m_stDataFileName = dbname; m_stDataFileName += ".epk"; Changez comme bon vous semble en conservant 3 caractères après le point. Vous devrez ensuite changer l'option sur votre packer, puis utiliser ceci (IF) pour changer les extensions de vos packs : main @echo OFF @echo Modifiez l'extension @echo de vos fichiers :rename set EIX= set /P EIX=Choisissez l'extension de vos futurs fichiers EIX: %=% @ren *.eix *.%EIX% @echo Succès .%EIX% if "%EIX%" == "" GOTO errore set EPK= set /P EPK=Choisissez l'extension de vos futurs fichiers EPK: : %=% if "%EPK%" == "" GOTO errore @ren *.epk *.%EPK% @echo Succès .%EPK% @echo --- GOTO fine :errore @echo Erreur ! @echo L'extension n'est pas valide ! @echo --- GOTO esciprogramma :fine @echo Le changement est terminé ! Quittez le programme. :esciprogramma @pause :rename set EIX= set /P EIX=Choisissez l'extension de vos futurs fichiers EIX: %=% @ren *.eix *.%EIX% @echo Succès .%EIX% if "%EIX%" == "" GOTO errore set EPK= set /P EPK=Choisissez l'extension de vos futurs fichiers EPK: : %=% if "%EPK%" == "" GOTO errore @ren *.epk *.%EPK% @echo Succès .%EPK% @echo --- GOTO fine :errore @echo Erreur ! @echo L'extension n'est pas valide ! @echo --- GOTO esciprogramma :fine @echo Le changement est terminé ! Quittez le programme. :esciprogramma @pause Bien, je pense qu'on peut s'arrêter là, j'ai plus de temps... Et je n'ai plus vraiment d'idée je vais compléter plus tard si nécessaire. je suis consciente que des tutoriels ont déjà été publiés sur ce sujet, mais il fallait bien les regrouper au lieu d'en faire 9000 partout, si quelqu'un à donc d'autre proposition je suis preneuse. Je suis pas forcément limitée au niveau de la programmation surtout au niveau C++, donc n'hésitez pas si vous avez besoin, je connais mal le jeu, je ne sais pas quels sont les plus gros cheats, comment ils fonctionnent etc... Bonne soirée ! On ne doit pas avoir accès aux box d'alertes, c'est dommage, ça m'a cassé toute ma mise en page...
  9. Le titre est assez imprécis, j'ai regardé très brièvement le code, et je ne suis pas familiarisée avec le Python, mais cela sert à savoir si Oui, ou non l'entrepôt est ouvert non ? Il ne crée pas un événement quand celui-ci se ferme si ? Merci de ton partage.
  10. Item/mob proto coté client

    Bonsoir, Contenu Masqué Je ne t'écris pas de tuto pour t'en servir, et pour retraduire en SQL/TXT etc. Je voulais pas mettre plus de temps à te répondre que les cinq secondes que tu as dû consacrer à ton poste pour ne même pas avoir mit une seule formule de politesse.
  11. annonce Bonne année !

    C'est toi l'enfant oui. Bonne année !
  12. Elle est inutile sauf que je conseil de s'habituer à la mette tout le temps, au moins pas de problème d'oublie dans les autres fichiers. Pensez juste à ne rien mettre après la balise, même des lignes vides, ça générerait du code HTML inutile. @Takuma C'est exactement ça. @ASIKOO Non, des petit carrés qu'on peut relier par des traits et mettre un peu où on veut, je l'avais vu sur un autre site il me semble, si je le retrouve je te le montrerais. @Holly Heureuse que ça te plaise
  13. Salut ! Avant de suivre cette partie, je vous invite à lire la précédente : Je vais ici essayer de vous faire découvrir HTML, CSS, JS et PHP. Voici les différents objectives de cette partie : Découvrir les éléments basiques de l'HTML tels que : La doctype Différents balises : Les principales balises telles que le p,h1,ul,td... Les principales balises orphelines telles que le hr, br... Les formulaires qui seront très utiles pour la suite, Les tableaux, Les liaisons : CSS, JS. PHP : Découverte de PDO : Créer sa requête : Préparation, Insertion de données, Exécution, Traiter les données : Nombre de ligne affectée, Colonne affectée, Ligne des colonnes affectées. Divers. Nous avons un emploi du temps assez chargé, nous ferions mieux de nous y mettre maintenant ! HTML: HTML est un langage de balisage. Il dispose de balise. Je vous propose une petite liste, qui résume les principales balises. @ASIKOO Il faudrait un système pour faire des cartes mentales ! ! (Je sais pas si c'est toi que je devais taguer, mais tu m'as l'air d'être le seul actif...). Sauf si je précise que les balises sont orphelines, elles devront être ouvertes puis fermées. Utilisez pour les fermer la même balise que pour les ouvrir, mais ajoutez un "/" exemple : <p>Message</p> Des balises assez spéciales : <!DOCTYPE html> Elle au dessus de tout votre code HTML. Elle est obligatoire, même si le code marche sans, pas de question, c'est obligatoire. Balise orpheline. <head>.. </head> Se place après la balise de doctype. Elle contient les informations complémentaires de la pages telles que : Le titre, Les mots clés, Les importations de : CSS, JS. Toutes les méta-informations. <body> .. </body> Se place après la balise de fermeture </head> Contient littéralement le corps de la page. C'est tout ce qui sera affiché au client. Les balises principales : Texte brut : <p> : Permet de rédiger un paragraphe. <h1>,<h2>... <h6> Permet d'écrire un titre plus ou moins important. L'évolution de l'importance est décroissante par rapport à la valeur associée à h. Les tableaux, un tableau ce compose de ces balises : <table> : Désigne le début et la fin du tableau, <tr> : Désigne une ligne du tableau, <td> : Désigne une cellule du tableau. On va donc créer un tableau comme ceci : <table> --> On crée le tableau <tr> --> On crée une nouvelle ligne <td>.. </td> --> On crée les colonnes en désignant les cellules </tr> --> On marque la fin de la ligne <tr> --> On crée une nouvelle ligne <td>.. </td> --> On crée les colonnes en désignant les cellules </tr> --> On marque la fin de la ligne </table> --> On marque la fin du tableau Il existe aussi (mais nous en reparlerons si nécessaire) : <thead> <tfoot> <tbody> Liste dite ordonnée : <ol> <li> élément </li> </ol> Liste dite non ordonnée : <ul> <li> élément </li> </ul> Je n'ai pas d'autre balise en tête dans l'instant présent. Si une balise que l'on va utiliser n'est pas présente dans ce petit regroupement, je vous l'expliquerais le moment venu. Je vais maintenant vous parlez des liaisons. Si vous ne le savez pas encore l'html, le css, et le javascript ne se mettent pas dans le même fichier pour des raisons évidentes de : Propretés, Efficacités Facilités. Il y a deux types de lignes différents qui se mettent tous les deux dans l'entête (head) du fichier html : <link href="assets/css/style.css" rel="stylesheet"> Ici, nous importons, créons un lien entre les deux fichiers. Notez que la seule valeur à changer est celle du href="" (Qui désigne une destination) vers la destination du fichier voulu. <script src="assets/js/modernizr.js"></script> Cette balise est assez bizarre je sais. Vous n'avez qu'à changer la destination nécessaire dans la valeur de l'attribue src. Je vous propose d'entamer maintenant PHP, PDO : PHP --> PDO: Bien, je vous rappelle que nous avons déjà crée notre connexion PDO stockée dans la variable db. Je vous propose pour commencer de déjà vous apprendre à créer une fonction en php. Une fonction vous permet d'effectuer un protocole plus ou moins long sans devoir le retaper entièrement. C'est le même principe que les fonctions en mathématiques, sauf qu'ici, nous ne faisons pas qu'ajouter des nombres, multiplier, etc... La structure d'une fonction est assez simple : <?php function GetUserIP(){ } ?> Ici, nous avons crée notre fonction nommée GetuserIP. Si votre fonction prends en compte des paramètres, (comme un x en mathématiques par exemple), vous les ajouterez entre les parenthèses, sous forme de variable, et séparés par des virgules. Ici, je vous montre une fonction assez technique, ça va peut-être, être même la fonction la plus compliquée que nous allons faire avec ce CMS. Car clairement... Il n'y a rien de compliqué sur un CMS Metin2. Bien, avant de commencer à écrire notre code, il sera préférable de savoir exactement ce que va faire la fonction. Pour des raisons de sécurités, nous allons vérifier que l'utilisateur dispose bien d'une IP valide, et que le serveur peut "capter". On ne sera pas à l'abri des VPNs, mais c'est déjà mieux que rien. Nous allons définir pour commencer trois variables qui contiendront : client L'ip de la personne enregistrée si possible forward L'ip malgré un proxy remote L'ip du client qui demande la page courante Pour cela nous allons utiliser une super variable. Si vous avez lu l'autre tutoriel, vous savez que les supers variables commencent toutes pas : $_ ici, nous allons utiliser la super variable server, donc : $_SERVEUR. Pour client et forward, nous allons mettre un arobase devant le dollars. Pour un soucis de type, je m'attarde pas là dessus, nous ne l'utiliserons plus de toute façon... Vous ne pouvez pas deviner le code, sauf si vous chercher des heures sur la doc, cela donne : <?php $client = @$_SERVER['HTTP_CLIENT_IP']; $forward = @$_SERVER['HTTP_X_FORWARDED_FOR']; $remote = $_SERVER['REMOTE_ADDR']; ?> Bien, nous allons maintenant vérifier si au moins client ou forward à le format d'une IP, sinon, nous utiliserons remote. Nous allons pour ça faire un bloc de condition facilement représentable grâce à ce schéma : On définie la variable client On définie la variable forward On définie la variable remote Si client ressemble à une IP valide, si oui : On assimile sa valeur à une autre variable nommée IP Si client n'a pas l'air d'être une IP valide : On vérifie si forwad là, si oui : On assimile sa valeur à une autre variable nommée IP Sinon : On assimile la valeur de remote à la variable nommée IP. Pour vérifier son format, on va utiliser une filtre, pas d'expression régulière c'est démodée. Vous ne pouvez pas le deviner, cela donne : <?php $client = @$_SERVER['HTTP_CLIENT_IP']; $forward = @$_SERVER['HTTP_X_FORWARDED_FOR']; $remote = $_SERVER['REMOTE_ADDR']; if(filter_var($client, FILTER_VALIDATE_IP)){ $ip = $client; }elseif(filter_var($forward, FILTER_VALIDATE_IP)){ $ip = $forward; }else{ $ip = $remote; } ?> On utilise donc les outils if --> Il veut dire "Si", soit : Si ce que je te dis dans la parenthèse est vrai (=true) alors : Il fait ce qu'il y a entre les accolades. Si la condition est respectée, on sort de la boucle. elseif marche comme le if à une différence près : Il ne peut être placé qu'après un if Ne s'exécutera que si le if n'est pas respecté Si la condition est respectée, on sort de la boucle. else --> Si aucune des conditions n'est respectées, le code fait ce qui se trouve dans le else. Sachez que additionner des if à la suite, et mettre des elseif n'a pas le même effet. Si vous enchainez des if, le code va tous les essayer un par un. Si vous mettez des elseif, il va tous les vérifier dans l'ordre, mais dès qu'il aura trouvé une solution, il ne va plus suivre les autres elseif de ce bloc. Il ne nous reste plus qu'une chose à faire : Vérifier si la variable IP est définie Si non : On sort de la condition en affichant une erreur Si oui : On retourne l'IP en sortit de variable Je vous montre une autre façon de faire un if (pas de panique, il n'en n'existe que deux) je vous explique après, notre fonction donne : <?php function GetUserIp(){ $client = @$_SERVER['HTTP_CLIENT_IP']; $forward = @$_SERVER['HTTP_X_FORWARDED_FOR']; $remote = $_SERVER['REMOTE_ADDR']; if(filter_var($client, FILTER_VALIDATE_IP)){ $ip = $client; }elseif(filter_var($forward, FILTER_VALIDATE_IP)){ $ip = $forward; }else{ $ip = $remote; } if(!isset($ip)) exit("ERREUR"); return $ip; } ?> Quelques petites précisions : La méthode exit permet de retourner une erreur et d'arrêter le script actuel, il va bloquer l'utilisateur. La méthode return permet de sortir de la fonction en retournant une valeur, ici l'ip. La méthode isset() permet de vérifier si une valeur est définie ou non. Ajouter un ! devant des méthodes telles que isset inverse leur fonctionnement. En quelque sorte nous faisons ici : Si l'ip n'est pas définie : Tu dégages le mec avec un bon coup de pied au cul Sinon, tu le laisse passer ! Et voilà vous avez fait votre première fonction ! Et pas des plus facile en plus. S'il y a du code que vous ne comprenez pas. La divine bible est là pour vous. Bien, allons enfin au vif du sujet : PDO. Pour envoyer une query au serveur, nous allons : Stocker notre requête dans une variable Lui attribuer des paramètres si nécessaires Exécuter la requête. Pour cela nous allons stocker notre requête dans une variable en utilisant un facteur d'affectation. Nous allons pour ça nous servir de la variable DB de la dernière fois. Si vous utilisez la variable $db dans une fonction, il faudrait que vous refassiez un include dans cette même fonction. Bien, on va préparer une query, on va utiliser : db->prepare(query); On va assigner ça à la variable $Akihira par exemple, tapons : <?php $Akihira = $db->prepare(); ?> Bien, nous allons taper une query au hasard, par exemple une assez simple : <?php $Akihira = $db->prepare("SELECT * FROM account.account"); ?> Bien, ici pas besoin d'attribuer des paramètres, vous pouvez exécuter votre fonction comme ceci : <?php $Akihira = $db->prepare("SELECT * FROM account.accoun"); $Akihira->execute(); ?> Maintenant, nous avons trois façon de récupérer des informations sur ce que nous avons fait : Savoir combien de ligne ont été affectée, ici cela nous renvoie le nombre de compte crée en réalité? rowCount(); Sélectionner les lignes affectées avec les colonnes indiqués fetch(); Sélectionner toutes les les colonnes de toutes les lignes affectées. fetchAll(); Bien, pour le rowCount(); c'est le plus simple, tapez : <?php $Akihira = $db->prepare("SELECT * FROM account.accoun"); $Akihira->execute(); $Akihira = $Akihira->rowCount(); ?> Ici, comme nous avons tout sélectionner ("*"), au niveau où vous êtes pour l'instant, il n'y a pas de différence, mais ne vous habituez pas à ça, il y en aura bientôt ! Pour le fetch, il va vous créer un tableau, il va falloir utiliser une méthode spécial pour obtenir les résultats. Mais on va voir ça dans un prochaine tutoriel où je vous parlerais plus en détails des tableaux, et on verra aussi la boucle foreach je pense pour pouvoir parler plus en détail du fetchAll. En attendant je vous dis merci d'avoir lu, et référé vous à la doc en attendant Salut !
  14. La page de vote c'est le plus simple ! Tu as 90% des codes déjà disponibles sur le topMetin2. Il ne te resteras plus qu'à faire la query pour créditer les monnaies au compte.
  15. Salut ! Merci beaucoup ! Je vais essayer ce soir de faire une autre partie avec les classements. Je suis assez prise ce soir. Je vais voir ce que je peux faire. Tu as des préférences dans l'ordre ? Bonne soirée !
×

Information importante

By using this site, you agree to our Conditions d’utilisation.