dimanche 17 février 2013

[AutoIT] Mettre en pause / relancer les torrents

Existant


Avant tout, je me dois de vous donner l'existant afin que vous vous projetiez bien dans l'idée.
J'ai un ordinateur sous Mint (une distribution GNU/Linux), qui fonctionne en continu dans une pièce de ma maison, dans laquelle je vais très peu.
Sur ce pc, j'ai Transmission (un client torrent) qui tourne sur lequel je télécharge tout pleins de film/musique en copyleft évidemment.
Je m'en sers comme mediacenter étant donné qu'il est connecté avec ma Neufbox et ushare, ce qui me permet de voir les films qui sont sur mon pc depuis ma télé (elle aussi branché à ma Neufbox).

Le petit problème, c'est que a chaque fois que ma femme veut jouer à des jeux en ligne, elle me demande de couper les téléchargements.
Alors j'avais activé Transmission Web Interface (TWI), en local, pour qu'elle puisse aller couper les téléchargements quand elle voulait jouer, ce qu'elle a très vite adopté, mais par contre remettre en route les téléchargements était moins évident pour elle.

Et de là, l'idée met venue de créer une application sous AutoIT (un langage de développement).
Etant donnée que globalement, le seul jeu auquel elle joue est Team Fortress 2, j'ai vite réflechi à une routine basique :

Si le processus hl2.exe (half-life 2, le moteur sur lequel tourne TF2) est trouvé, on met en pause les téléchargements, et une fois qu'il re-disparaît on relance les téléchargements.

Mais avant tout il faut savoir comment fonctionne la Transmission Web Interface (TWI), et analyser les packets envoyés lorsqu'on se connecte, lorsqu'on appui sur le bouton pour mettre en pause ou relancer les téléchargements pour imiter leur comportement depuis notre automate.

Etude

Les logiciels utilisés :
Les addons Firefox utilisés :
  • Tamper Data : permet d’altérer les packets en live
  • Live HTTP Headers : pour juste lire les packets (Tamper Data fait aussi ca, mais j'aime bien utiliser celui ci pour la lecture)

Alors, avant de nous lancer on va poser les idées...

Nous allons lancer Wireshark pour écouter la conversation entre mon navigateur et le serveur web qui répond.
Et à l'aide de Live HTTP Headers, on va lire ce qui se passe lorsque j'appuie sur le bouton pour relancer les téléchargements et lorsque j'appui sur le bouton pour mettre en pause les téléchargements afin de nous faire une idée claire.

Effectivement, je pourrais utiliser que Wireshark, si je le voulais pour cela, mais j'ai ce besoin de m'étendre afin d'être sur que tout est claire (et je ne maîtrise pas très bien Wireshark encore).

Alors on ouvre notre TWI depuis notre navigateur:


Il nous est demandé nos identifiants (login+pass).

On va déjà regarder la requête envoyé, et celle reçue :

GET / HTTP/1.1
Host: 192.168.1.47:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive


HTTP/1.1 401 Unauthorized
Server: Transmission
WWW-Authenticate: Basic realm="Transmission"
Date: sam., 16 févr. 2013 11:35:05 GMT
Content-Length: 43
Content-Type: text/html; charset=ISO-8859-1

On peut voir que une requête tout à fait basique à été envoyé, et la réponse-code étant "401" , ce qui signifie qu'il manque les droits d'accès dans notre requête HTTP.
On va donc se connecter, et voir où sont stocker ces informations.

Voici la requête envoyé lorsque j'ai entré mes identifiants :
  • Identifiant: admin
  • Password : test

GET / HTTP/1.1
Host: 192.168.1.47:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Cookie: compact_display_state=true; sort_method=ratio
Connection: keep-alive
Authorization: Basic YWRtaW46dGVzdA==

La dernière ligne contient très probablement l'identifiant et le mot de passe, d'ailleurs lorsque je vois ce genre de hash "YWRtaW46dGVzdA==" des caracteres miniscules, majuscules, et un égal à la fin j'ai le reflex de d'aller dechiffrer ceci en ASCII.

A l'aide de ce convertisseur en ligne base64 vers ascii  (www.base64decode.org), on peut constater que notre hash contient : "admin:test".
Vous l'aurez compris l'identifiant et le password séparés par un deux points
C'est un point à ne pas oublier lorsque l'on fera l'application qui automatisera la routine d'identification.

Présentation rapide du TWI, en deux images :





J'ai donc lancé Wireshark, et mis le filtre suivant :
  • ip.dst == 192.168.1.47 && http
Ce qui m'a permit de voir les requêtes envoyés seulement et j'ai appuyé sur le bouton relancer les téléchargements et mettre en pause.
J'ai ensuite cherché les packets correspondant dans Wireshark et j'ai trouvé ces deux packets interessant :


Ce packet la est surement celui pour relancer les téléchargements, le "torrent-start" est assez parlant.



Ce packet là est surement le packet pour mettre en pause les téléchargements :

0000   7b 22 6d 65 74 68 6f 64 22 3a 22 74 6f 72 72 65  {"method":"torre
0010   6e 74 2d 73 74 6f 70 22 2c 22 61 72 67 75 6d 65  nt-stop","argume
0020   6e 74 73 22 3a 7b 22 69 64 73 22 3a 5b 31 2c 32  nts":{"ids":[1,2
0030   2c 33 2c 34 2c 35 2c 36 2c 37 2c 38 2c 39 2c 31  ,3,4,5,6,7,8,9,1
0040   30 2c 31 31 2c 31 32 2c 31 33 2c 31 34 2c 31 35  0,11,12,13,14,15
0050   2c 31 36 2c 31 37 2c 31 38 5d 7d 7d              ,16,17,18]}}

Si on met cela en claire on est donc face à un packet json sous cette forme:
{
   "method" : "torrent-stop",
   "arguments":
   {
      "ids" : [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18]
   }
}

Donc en gros on demande de mettre en pause les téléchargements : 1 , 2 ... 17,18.
On va donc devoir tester avec Tamper Data si je retire les arguments si TWI met en pause tout les téléchargements ou bien si il va falloir que d'abord je récupère la liste entière.

J'ai donc alteré le packet au moment ou j'ai appuyé sur le bouton, et j'ai juste envoyé :
{ "method" : "torrent-stop" }

Et avec chance, cela à fonctionné ce qui va nous éviter d'avoir à envoyé un packet pour récupérer la liste, ce qui nous aurait demandé un peu plus de ligne.

La requête récupérer à l'aide de Live HTTP Headers:

POST /transmission/rpc HTTP/1.1
Host: 192.168.1.47:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: ; charset=UTF-8
X-Transmission-Session-Id: dGJ5RPdg690BjdHS6uemZUgayme61nWtEbTNtv1Ok9R2wCQQ
X-Requested-With: XMLHttpRequest
Referer: http://192.168.1.47:8080/transmission/web/
Content-Length: 92
Cookie: compact_display_state=true; sort_method=ratio
Authorization: Basic YWRtaW46dGVzdA==
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
{"method":"torrent-stop","arguments":{"ids":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18]}}

Nous allons construire notre requête à envoyé pour couper tous les téléchargements:

Donc avant tout, on a constaté qu'on pouvait retirer les arguments du packet ce qui transforme notre dernière ligne par : 

{"method":"torrent-stop"}

Etant donnée, que le contenu à moins de caractère il faut changer aussi l'élement : Content-Length.

Ce qui transforme la ligne : 
Content-Length : 92
par 
Content-Length : 24

Requête pour mettre en pause fini: 

POST /transmission/rpc HTTP/1.1
Host: 192.168.1.47:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: ; charset=UTF-8
X-Transmission-Session-Id: dGJ5RPdg690BjdHS6uemZUgayme61nWtEbTNtv1Ok9R2wCQQ
X-Requested-With: XMLHttpRequest
Referer: http://192.168.1.47:8080/transmission/web/
Content-Length: 24
Cookie: compact_display_state=true; sort_method=ratio
Authorization: Basic YWRtaW46dGVzdA==
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
{"method":"torrent-stop"}

On fait la même chose pour la requête pour relancer les téléchargements ce qui nous donne : 

POST /transmission/rpc HTTP/1.1
Host: 192.168.1.47:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: ; charset=UTF-8
X-Transmission-Session-Id: dGJ5RPdg690BjdHS6uemZUgayme61nWtEbTNtv1Ok9R2wCQQ
X-Requested-With: XMLHttpRequest
Referer: http://192.168.1.47:8080/transmission/web/
Content-Length: 25
Cookie: compact_display_state=true; sort_method=ratio
Authorization: Basic YWRtaW46dGVzdA==
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
{"method":"torrent-start"}

On peut aussi remarquer qu'il y a un élément appelé : X-Transmission-Session-Id celui doit surement être crée à l'authentification.
C'est le serveur qui vous donne un numéro de session (ici : dGJ5RPdg690BjdHS6uemZUgayme61nWtEbTNtv1Ok9R2wCQQ) et que votre navigateur une fois reçu ré-utilise pour que le serveur sache qui vous êtes.
Et si on ne donne pas cette session, on peut être sûr que la TWI ignorera nos commandes.

Il faut donc que l'on trouve comme est crée cette session, j'ai donc fait une recherche dans Wireshark, et avec étonnement la session n'est pas crée à l'authentification, mais lorsque je le demande avec un packet :

{"method":"session-get"}

Le serveur me répond : 

HTTP/1.1 409 Conflict
Server: Transmission
X-Transmission-Session-Id: dGJ5RPdg690BjdHS6uemZUgayme61nWtEbTNtv1Ok9R2wCQQ
Date: sam., 16 févr. 2013 12:07:24 GMT
Content-Length: 580
Content-Type: text/html; charset=ISO-8859-1

On va juste retenir que la réponse-code est 409, et que le session-id est donné dans le header de réponse, il se peut que cela nous soit utile.

On verra à la conception comment récupérer cette session-id, on sait la demander, c'est déjà bien.


Test sous AutoIT

Les logiciels utilisées :

Avant tout, j'aimerais m'expliquer concernant le langage choisi.
Effectivement, j'ai choisi AutoIT pour mener à bien cette application, car j'avais déjà un peu travailler sur les requêtes HTTP sur ce langage pour faire un "Bot Vote" pour le serveur privée Ivalice (source ici)  et cela ne m'oblige pas à installer Python sur la machine de ma femme.

Alors nous allons avant tout concevoir, une fenêtre avec deux boutons : Start et Pause, juste pour essayer et commencer à concevoir notre routine.

J'utilise Koda, qui est installé automatiquement avec SciTE, qui permet de agencer la GUI de notre application :




Voilà la source de la GUI :

  1. #include <ButtonConstants.au3>
  2. #include <GUIConstantsEx.au3>
  3. #include <WindowsConstants.au3>
  4. #Region ### START Koda GUI section ### Form=
  5. $Form1 = GUICreate("Form1", 184, 43, 503, 224)
  6. $bStart = GUICtrlCreateButton("Start", 8, 8, 75, 25)
  7. $bPause = GUICtrlCreateButton("Pause", 96, 8, 75, 25)
  8. GUISetState(@SW_SHOW)
  9. #EndRegion ### END Koda GUI section ###
  10. While 1
  11.         $nMsg = GUIGetMsg()
  12.         Switch $nMsg
  13.                 Case $GUI_EVENT_CLOSE
  14.                         Exit
  15.         EndSwitch
  16. WEnd

Je ne vois pas trop quoi commenter sur cette source, il y a les includes nécessaires aux fonctions utilisées, et une boucle infini pour faire tourner la fenêtre sans interruption avec un Switch sur les évènements

On veut que lorsque j'appui sur Start ou Pause, une routine soit lancée :
  • Demander une session
  • Récupérer le session-id
  • Envoyé la commande de lancement des téléchargements ou de mise en pause selon le bouton appuyé.
On va avant tout créer notre fonction pour demander et récupérer notre session:

  1. Func createSession()
  2.         $oHTTP = ObjCreate("winhttp.winhttprequest.5.1")
  3.         $oHTTP.Open("POST", "http://192.168.1.47:8080/transmission/rpc", False)
  4.         $oHTTP.SetRequestHeader('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0')
  5.         $oHTTP.SetRequestHeader('Accept', 'application/json, text/javascript, */*; q=0.01')
  6.         $oHTTP.SetRequestHeader('Accept-Language', 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3')
  7.         $oHTTP.SetRequestHeader('Accept-Encoding', 'gzip, deflate')
  8.         $oHTTP.SetRequestHeader('Content-Type', 'charset=UTF-8')
  9.         $oHTTP.SetRequestHeader('X-Requested-With', 'XMLHttpRequest')
  10.         $oHTTP.SetRequestHeader('Referer', 'http://192.168.1.47:8080/transmission/web/')
  11.         $oHTTP.SetRequestHeader('Content-Length', '24')
  12.         $oHTTP.SetRequestHeader('Authorization', 'Basic YWRtaW46dGVzdA==')
  13.         $oHTTP.SetRequestHeader('Connection', 'keep-alive')
  14.         ;creation de la requete
  15.         $oHTTP.Send('{"method":"session-get"}')
  16.         ;ce que l'on envoit pour recuperer le Session ID
  17.         $oReceived = $oHTTP.ResponseText
  18.         ConsoleWrite($oReceived)
  19.         ;nous donne le contenu de la page renvoyée
  20. End Func

et une fois exécuté cette fonction répond dans la console:

  1. <h1>409: Conflict</h1>
  2.   <p>Your request had an invalid session-id header.</p>
  3.   <p>
  4.     To fix this, follow these steps:
  5.     <ol>
  6.       <li>When reading a response, get its X-Transmission-Session-Id header and remember it
  7.       <li> Add the updated header to your outgoing requests<li> When you get this 409 error message, resend your request with the updated header
  8.     </ol>
  9.   </p>
  10.   <p>This requirement has been added to help prevent <a href="http://en.wikipedia.org/wiki/Cross-site_request_forgery">CSRF</a> attacks.</p>
  11.   <p><code>X-Transmission-Session-Id: VL36clQM8FJhuuk6Kd5AZjG4u1vxmqViUQU3j0DgnuqqYgzC</code></p

On voit bien que la dernière ligne est super interessante, donc avec une regex on pourrait recuperer ce qui est dans <code></code>

Donc on va revoir la fonction par :

  1. Func createSession()
  2.         $oHTTP = ObjCreate("winhttp.winhttprequest.5.1")
  3.         $oHTTP.Open("POST", "http://192.168.1.47:8080/transmission/rpc", False)
  4.         $oHTTP.SetRequestHeader('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0')
  5.         $oHTTP.SetRequestHeader('Accept', 'application/json, text/javascript, */*; q=0.01')
  6.         $oHTTP.SetRequestHeader('Accept-Language', 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3')
  7.         $oHTTP.SetRequestHeader('Accept-Encoding', 'gzip, deflate')
  8.         $oHTTP.SetRequestHeader('Content-Type', 'charset=UTF-8')
  9.         $oHTTP.SetRequestHeader('X-Requested-With', 'XMLHttpRequest')
  10.         $oHTTP.SetRequestHeader('Referer', 'http://192.168.1.47:8080/transmission/web/')
  11.         $oHTTP.SetRequestHeader('Content-Length', '24')
  12.         $oHTTP.SetRequestHeader('Authorization', 'Basic YWRtaW46dGVzdA==')
  13.         $oHTTP.SetRequestHeader('Connection', 'keep-alive')
  14.         ;creation de la requete
  15.         $oHTTP.Send('{"method":"session-get"}')
  16.         ;ce que l'on envoit pour recuperer le Session ID
  17.         $oReceived = $oHTTP.ResponseText
  18.         ConsoleWrite($oReceived)
  19.         ;nous donne le contenu de la page renvoyée
  20.         $array = StringRegExp($oReceived, "<(?i)code>(.*?)</(?i)code>", 1)
  21.         ;array[0] contient le nombre de valeur dans le tableau
  22.         ;array[1] du vide
  23.         ;array[2] contient : X-Transmission-Session-ID: le_Session_ID
  24.         ;on va donc separer en deux en utilisant le delimiteur espace pour juste recuperer le_Session_ID
  25.         $array = StringSplit($array[0], " ", 1)
  26.         ;array[0] contient 2 (le nombre de valeur dans le tableau
  27.         ;array[1] contient X-Transmission-Session-ID
  28.         ;array[2] contient le_Session_ID
  29.         return $array[2] ;on renvoit donc $array[2]
  30. EndFunc

C'est parfait ! la fonction me retourne ce qu'on lui demande.

Maintenant il faut créer une fonction start, et une fonction pause.
Je vais vous proposer une fonction qui peut faire les deux, ça réduira la taille de l'application.

  1. Func createPacket($action)
  2.         $lenght = _Iif($action == 'start', '26', '25') ;si $action == start, alors $lenght == 26 sinon == 25
  3.         $ssid = createSession() ; ici on stocke le_Session_ID
  4.         sleep(100)
  5.         $oHTTP = ObjCreate("winhttp.winhttprequest.5.1")
  6.         $oHTTP.Open("POST", "http://192.168.1.47:8080/transmission/rpc", False)
  7.         $oHTTP.SetRequestHeader('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0')
  8.         $oHTTP.SetRequestHeader('Accept', 'application/json, text/javascript, */*; q=0.01')
  9.         $oHTTP.SetRequestHeader('Accept-Language', 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3')
  10.         $oHTTP.SetRequestHeader('Accept-Encoding', 'gzip, deflate')
  11.         $oHTTP.SetRequestHeader('Content-Type', 'charset=UTF-8')
  12.         $oHTTP.SetRequestHeader('X-Transmission-Session-Id', $ssid)
  13.         $oHTTP.SetRequestHeader('X-Requested-With', 'XMLHttpRequest')
  14.         $oHTTP.SetRequestHeader('Referer', 'http://192.168.1.47:8080/transmission/web/')
  15.         $oHTTP.SetRequestHeader('Content-Length', $lenght)
  16.         $oHTTP.SetRequestHeader('Authorization', 'Basic YWRtaW46dGVzdA==')
  17.         $oHTTP.SetRequestHeader('Connection', 'keep-alive')
  18.         $oHTTP.Send('{"method":"torrent-' & $action & '"}')
  19.         ; le contenu de la requete soit {"method" : "torrent-start"} ou ... stop :P
  20. EndFunc

et donc maintenant faut appeler les fonctions quand on clique sur les boutons :

  1. While 1
  2.         $nMsg = GUIGetMsg()
  3.         Switch $nMsg
  4.                 Case $GUI_EVENT_CLOSE
  5.                         Exit
  6.                 Case $bStart
  7.                         $packet = createPacket("start")
  8.                 Case $bPause
  9.                         $packet = createPacket("stop")
  10.         EndSwitch
  11. WEnd


J'ai testé, et cela fonctionne très bien.
Ce qui met un terme à cette partie, on va donc attaquer la programmation de l'application.


L'Application

Alors je répète un peu le fonctionnement de l'application, c'est une application qui fonctionne en continu et de manière discrète en vérifiant de manière cyclique si hl2.exe apparaît dans la liste des processus, si c'est le cas on appelle la fonction createPacket("stop") et on vérifie de manière cyclique si le processus hl2.exe disparaît  et ainsi de suite...

Je vais tout de même laisser la GUI, car si jamais elle veut pouvoir couper, si elle joue à un autre jeu, elle aura la possibilité de le faire manuellement.

et voilà la source:

  1. #include <ButtonConstants.au3>
  2. #include <GUIConstantsEx.au3>
  3. #include <WindowsConstants.au3>
  4. #include <misc.au3>
  5. #include <Array.au3>
  6. Opt("TrayMenuMode", 3)
  7. Opt("TrayAutoPause", 0)
  8. $Form1 = GUICreate("Remote Control", 237, 42, 375, 150,BitOR($GUI_SS_DEFAULT_GUI,$WS_MAXIMIZEBOX,$WS_SIZEBOX,$WS_THICKFRAME,$WS_TABSTOP))
  9. $bStart = GUICtrlCreateButton("Start", 8, 8, 75, 25)
  10. $bPause = GUICtrlCreateButton("Pause", 144, 8, 75, 25)
  11. $tShow = TrayCreateItem("Afficher")
  12. $tExit = TrayCreateItem("Quitter")
  13. GUISetState(@SW_HIDE) ;cache la fenetre au lancement
  14. Func createSession()
  15.         $oHTTP = ObjCreate("winhttp.winhttprequest.5.1")
  16.         $oHTTP.Open("POST", "http://192.168.1.47:8080/transmission/rpc", False)
  17.         $oHTTP.SetRequestHeader('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0')
  18.         $oHTTP.SetRequestHeader('Accept', 'application/json, text/javascript, */*; q=0.01')
  19.         $oHTTP.SetRequestHeader('Accept-Language', 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3')
  20.         $oHTTP.SetRequestHeader('Accept-Encoding', 'gzip, deflate')
  21.         $oHTTP.SetRequestHeader('Content-Type', 'charset=UTF-8')
  22.         $oHTTP.SetRequestHeader('X-Requested-With', 'XMLHttpRequest')
  23.         $oHTTP.SetRequestHeader('Referer', 'http://192.168.1.47:8080/transmission/web/')
  24.         $oHTTP.SetRequestHeader('Content-Length', '24')
  25.         $oHTTP.SetRequestHeader('Authorization', 'Basic YWRtaW46dGVzdA==')
  26.         $oHTTP.SetRequestHeader('Connection', 'keep-alive')
  27.         $oHTTP.Send('{"method":"session-get"}')
  28.         $oReceived = $oHTTP.ResponseText
  29.         $array = StringRegExp($oReceived, "<(?i)code>(.*?)</(?i)code>", 1)
  30.         $array = StringSplit($array[0], " ", 1)
  31.         return $array[2]
  32. EndFunc
  33. Func createPacket($action)
  34.         $lenght = _Iif($action == 'start', '26', '25') ;si $action == start, alors $lenght == 26 sinon == 25
  35.         $ssid = createSession() ; ici on stocke le_Session_ID
  36.         sleep(100)
  37.         $oHTTP = ObjCreate("winhttp.winhttprequest.5.1")
  38.         $oHTTP.Open("POST", "http://192.168.1.47:8080/transmission/rpc", False)
  39.         $oHTTP.SetRequestHeader('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0')
  40.         $oHTTP.SetRequestHeader('Accept', 'application/json, text/javascript, */*; q=0.01')
  41.         $oHTTP.SetRequestHeader('Accept-Language', 'fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3')
  42.         $oHTTP.SetRequestHeader('Accept-Encoding', 'gzip, deflate')
  43.         $oHTTP.SetRequestHeader('Content-Type', 'charset=UTF-8')
  44.         $oHTTP.SetRequestHeader('X-Transmission-Session-Id', $ssid)
  45.         $oHTTP.SetRequestHeader('X-Requested-With', 'XMLHttpRequest')
  46.         $oHTTP.SetRequestHeader('Referer', 'http://192.168.1.47:8080/transmission/web/')
  47.         $oHTTP.SetRequestHeader('Content-Length', $lenght)
  48.         $oHTTP.SetRequestHeader('Authorization', 'Basic YWRtaW46dGVzdA==')
  49.         $oHTTP.SetRequestHeader('Connection', 'keep-alive')
  50.         $oHTTP.Send('{"method":"torrent-' & $action & '"}')
  51. EndFunc
  52. AdlibRegister("CheckProcess", 5000) ;toutes les 5secondes on lance la fonction CheckProcess
  53. Global $statusDuProcessus = 0
  54. Func CheckProcess()
  55.         If $statusDuProcessus == 0 Then
  56.                 If ProcessExists("hl2.exe") Then
  57.                         createPacket("stop")
  58.                         $statusDuProcessus = 1
  59.                 EndIf
  60.         Else
  61.                 If Not ProcessExists("hl2.exe") Then
  62.                         createPacket("start")
  63.                         $statusDuProcessus = 0
  64.                 EndIf
  65.         EndIf
  66. EndFunc
  67. While 1
  68.         $nMsg = GUIGetMsg()
  69.         $tMsg = TrayGetMsg()
  70.         Switch $nMsg
  71.                 Case $GUI_EVENT_CLOSE
  72.                         GUISetState(@SW_HIDE) ;cache la fenetre si on appui sur la croix
  73.                 Case $GUI_EVENT_MINIMIZE
  74.                         GUISetState(@SW_HIDE) ;cache la fenetre si on appui sur minimize
  75.                 Case $bStart
  76.                         createPacket("start")
  77.                 Case $bPause
  78.                         createPacket("stop")
  79.         EndSwitch
  80.         Switch $tMsg
  81.                 Case $tShow
  82.                         GUISetState(@SW_SHOW) ;montre la fenetre si on appui sur Afficher dans le Tray
  83.                 Case $tExit
  84.                         Exit
  85.         EndSwitch
  86. WEnd

La source parle plutôt d'elle même.
En espérant que ce tutoriel, aura permit à certains de comprendre la logique de l'analyse de protocol, et comment ce le re-approprier.

n0wz