Last.fm

20:29 modifié dans API AppKit #1
Bonjour,

Je cherche à  intégrer last.fm à  mon logiciel qui permet le contrôle de iTunes.
Cependant, après 1 heure à  feuilleter le site last.fm je ne trouve rien qui permette simplement de se connecter à  son compte et à  envoyer les données de lecture..
Aucun framework, rien du tout quoi..
Si quelqu'un sait quelque chose là  dessus, je suis preneur.

Louka.
«1

Réponses

  • 20:29 modifié #2
    Apparemment ça serait ici : http://www.audioscrobbler.net/development/protocol/
    Donc aucun framework en vue et ça ne marcherait qu'avec des connections.. mais bon.
  • BruBru Membre
    20:29 modifié #3
    Ca cause via des web services.
    Y'a donc tout ce qu'il faut dans cocoa pour envoyer des requêtes, recevoir les réponses, puis les parser pour en extraire les infos.

    .
  • schlumschlum Membre
    20:29 modifié #4
    Et s'ils fournissent un wsdl, /Developer/Tools/WSMakeStubs permet de créer la classe Objective-C qui va bien.
  • 20:29 modifié #5
    Il y a un truc que je ne comprend pas :

    The algorithm for generating this token is as follows:

    token := md5(md5(password) + timestamp)

    Where timestamp is the same timestamp sent in cleartext in the handshake request.

    The md5() function takes a string and returns the 32-byte ASCII hexadecimal representation of the MD5 hash, using lower case characters for the hex values. The '+' operator represents concatenation of the two strings.


    En gros, je dois faire le md5 du password, ajouter l'Unix Timestamp puis refaire le md5 du tout.
    Cependant, ce que je ne vois pas c'est comment faire cette "addition". Car je suppose que coller le timestamp au md5 du password ne marchera pas ?
  • BruBru Membre
    20:29 modifié #6
    Le premier md5(password) te retourne une chaine représentant le password crypté.
    A cette chaine, tu concatènes le timestamp (chaine contanant un nombre).
    Tu obtiens donc une nouvelle chaine que tu vas à  nouveau crypter via md5().

    .
  • 20:29 modifié #7
    D'accord merci.

    Autre question.. md5.. comment je dois l'utiliser exactement ?
    D'après ce que m'a dit Psycho, le md5 du terminal n'est que pour les fichiers. Or là  je veux le faire, comme vous l'avez compris, à  partir d'un simple mot de passe..

    Merci d'avance pour votre aide.
    LouK
  • schlumschlum Membre
    janvier 2008 modifié #8
    md5 -s "<mot de passe>"

    Sinon, pour l'utiliser dans un programme -> "man 3 md5"

    #include &lt;openssl/md5.h&gt;<br /><br />&nbsp; &nbsp; &nbsp; &nbsp; unsigned char *MD5(const unsigned char *d, unsigned long n,<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  unsigned char *md);
    

  • BruBru Membre
    20:29 modifié #9
    Ou alors en utilisant openSSL (la lib libcrypto de mémoire), mais c'est un poil plus complexe que la commande md5 exposée par schlum.

    .
  • janvier 2008 modifié #10
    Merci beaucoup pour votre aide schlum et Bru :)
    Sinon j'avais téléchargé aussi le framework SSCrypto, ça aurait pu marcher aussi vous croyez ?
  • schlumschlum Membre
    20:29 modifié #11
    Oui, mais c'est un peu le marteau pour écraser la mouche...
    Une ligne suffit avec la fonction donnée dans le man ; il suffit de donner la chaà®ne, sa longueur, et un buffer pour le digest (16*sizeof(char))
  • 20:29 modifié #12
    quand tu parles de longueur, le cLength de NSString peut marcher ?
  • schlumschlum Membre
    janvier 2008 modifié #13
    dans 1199367444:

    quand tu parles de longueur, le cLength de NSString peut marcher ?


    Oui
    Par contre, attention ; en fonction de l'encodage, tu n'auras pas le même MD5 s'il y a des caractères non ASCII...

    Donc c'est plutôt "- (unsigned)lengthOfBytesUsingEncoding:(NSStringEncoding)enc" et "- (const char *)cStringUsingEncoding:(NSStringEncoding)encoding" qu'il faut utiliser
    Ou pour la compatibilité <10.4 : "- (const char *)UTF8String" et "strlen"
  • 20:29 modifié #14
    Oui j'avais déjà  était confronté à  ça sur le topic où je voulais encoder un NSDictionary pour le mettre sous forme d'URL :)
    Merci encore pour votre aide à  vous deux ;)
  • janvier 2008 modifié #15
    Y'a un truc que je comprend pas..
    Pourquoi ça :
    <br />NSString* pass = @&quot;test&quot;;<br /><br />	unsigned char *MD5([pass lengthOfBytesUsingEncoding:NSUTF8StringEncoding], [pass cStringUsingEncoding:NSUTF8StringEncoding],(16*sizeof(char)));<br />
    


    ça ne marche pas ?  ???

    Sinon via le terminal j'ai réussi !



    Autre question (et là  je pense que ça sera bon) : comment récupérer le timestamp ?  :o
    Parce que là  je l'ai fait à  la main, via un site où je rentre la date et me retourne l'Unix timestamp. Je n'ai trouvé que via le Terminal :
    <br />date +%s<br />
    
  • schlumschlum Membre
    20:29 modifié #16
    dans 1199372971:

    Y'a un truc que je comprend pas..
    Pourquoi ça :
    <br />NSString* pass = @&quot;test&quot;;<br /><br />	unsigned char *MD5([pass lengthOfBytesUsingEncoding:NSUTF8StringEncoding], [pass cStringUsingEncoding:NSUTF8StringEncoding],(16*sizeof(char)));<br />
    


    ça ne marche pas ?  ???


    Parce que c'est pas vraiment ça  :P
    unsigned char *MD5(const unsigned char *d, unsigned long n,unsigned char *md);
    

    ->
    unsigned char digest[16];<br />MD5([pass cStringUsingEncoding:NSUTF8StringEncoding],[pass lengthOfBytesUsingEncoding:NSUTF8StringEncoding],digest);
    


    (16*sizeof(char) c'était la taille du buffer de digest qu'il fallait allouer...)
  • 20:29 modifié #17
    dans 1199375961:

    dans 1199372971:

    Y'a un truc que je comprend pas..
    Pourquoi ça :
    <br />NSString* pass = @&quot;test&quot;;<br /><br />	unsigned char *MD5([pass lengthOfBytesUsingEncoding:NSUTF8StringEncoding], [pass cStringUsingEncoding:NSUTF8StringEncoding],(16*sizeof(char)));<br />
    


    ça ne marche pas ?  ???


    Parce que c'est pas vraiment ça  :P
    unsigned char *MD5(const unsigned char *d, unsigned long n,unsigned char *md);
    

    ->
    unsigned char digest[16];<br />MD5([pass cStringUsingEncoding:NSUTF8StringEncoding],[pass lengthOfBytesUsingEncoding:NSUTF8StringEncoding],digest);
    


    (16*sizeof(char) c'était la taille du buffer de digest qu'il fallait allouer...)


    Merci Schlum :) Vivement que je me mette au C ^^
  • 20:29 modifié #18
    Encore une chose, je n'arrive pas à  "additioner" les 2 NSString. Enfin j'ai une erreur lorsque je post l'URL au final alors que si je le fait à  la main dans le terminal ça marche.

    pourtant je fais [NSString stringWithFormat:@\%@%@\;"", md5Pass, timestamp] (que je rajoute dans les arguments pour en faire le MD5.

    md5pass est bon, timestamp aussi. Car si je fais ça à  la main via le terminal, c'est à  dire :
    md5 -s md5passtimestamp (bien sûr je remplace par les valeurs), ça marche bien, j'envoie ça sur l'URL et hop authentification OK
    Par contre, si je récupère l'AUTH via mon logiciel, ça ne marche pas.. enfin le md5 est mauvais. Je soupçonne donc l'assemblement du md5Pass et timestamp
  • AliGatorAliGator Membre, Modérateur
    20:29 modifié #19
    Pourquoi tu passes pas par la fonction C directement, vraiment ?
    Lancer le process "md5" (qui n'est qu'une bête encapsulation de la fonction C dans une ligne de commande) peut te mener à  des erreurs d'interprétation de paramètres.

    En particulier je ne sais pas comment tu lances ton process "md5", mais si tu le fais par une NSTask, alors dans les paramètres que l'on passe à  une NSTask on lui passe les arguments sous forme d'un NSArray, chaque argument étant un élément séparé du NSArray... ce n'est pas comme quand tu appelles une commande depuis le Terminal où, pour séparer les arguments, tu utilises le caractère espace... ce qui a pour effet qu'il faut alors utiliser les guillemets pour encapsuler les arguments avec un espace, guillemets qui sont enlevés par le SHELL (et non par le programme lancé) avant d'être passés en argv à  ton programme

    Conclusion ? Les guillemets sont de trop ici ! En plus la concaténation d'un MD5 (32 caractères héxadécimaux [0-9A-F]) et d'un timestamp (simple nombre [0-9]) ne devrait pas poser de problème pour le passage d'arguments, donc ils ne sont vraiment pas justifiés.

    Le fait de les mettre fait que, si tu lances ta NSTask en lui passant ta chaà®ne entre guillemets, il va calculer le md5 de cette chaà®ne... guillemets compris, comme si les guillemets faisaient partie de la chaà®ne ! Alors que [tt][task setArguments:[NSArray arrayWithObjects:@-s, md5passAndTimestamp, nil]][/tt] sépare déjà  les différents arguments, il prendra donc md5passAndTimestamp tel quel, guillemets compris si la chaà®ne en comporte.
  • schlumschlum Membre
    janvier 2008 modifié #20
    Une petite catégorie de NSString  ;)

    #import &lt;Cocoa/Cocoa.h&gt;<br /><br /><br />@interface NSString (StringMD5)<br /><br />- (NSString*)MD5HexHashFromUTF8Representation;<br /><br />@end
    


    #import &quot;StringMD5.h&quot;<br />#include &lt;openssl/md5.h&gt;<br />#include &lt;string.h&gt;<br /><br />@implementation NSString (StringMD5)<br /><br />- (NSString*)MD5HexHashFromUTF8Representation<br />{<br />	const char *utf8Rep = [self UTF8String];<br />	size_t lg = strlen(utf8Rep);<br />	unsigned char digest[16];<br />	char hexHash[33];<br />	MD5((const unsigned char*)utf8Rep,(unsigned long)lg,digest);<br />	int i,j;<br />	// Optimisable...<br />	for(i=0,j=0;i&lt;16;++i,j+=2)<br />		snprintf(hexHash+j,3,&quot;%02x&quot;,digest[i]);<br />	return [NSString stringWithUTF8String:hexHash];<br />}<br /><br />@end
    




    Et cas plus général, mais >=10.4

    - (NSString*)MD5HexHashWithEncoding:(NSStringEncoding)encoding upperCase:(bool)upper<br />{<br />	const char *rep = [self cStringUsingEncoding:encoding];<br />	unsigned int lg = [self lengthOfBytesUsingEncoding:encoding];<br />	unsigned char digest[16];<br />	char hexHash[33];<br />	MD5((const unsigned char*)rep,(unsigned long)lg,digest);<br />	int i,j;<br />	// Optimisable...<br />	for(i=0,j=0;i&lt;16;++i,j+=2)<br />		snprintf(hexHash+j,3,upper?&quot;%02X&quot;:&quot;%02x&quot;,digest[i]);<br />	return [NSString stringWithUTF8String:hexHash];<br />}
    
  • janvier 2008 modifié #21
    Il y a un truc que je ne comprend pas (encore :D). Pourquoi tu as rajouté une valeur booléenne upperCase ? Le passage où tu l'utilises je ne comprend pas à  quoi ça sert exactement (même si je sais que ça sert à  mettre un NSString en capitale)

    Pour te répondre Ali, oui mon NSTask je l'ai très bien fait, c'est juste le md5 final qui semblait pas bon du tout.. J'ai bien séparé les arguments par des objets dans une NSArray et non par des espaces

    (J'ai une erreur _MD5 referenced from). Malgré l'import de openssl/md5)
  • schlumschlum Membre
    20:29 modifié #22
    dans 1199450148:

    Il y a un truc que je ne comprend pas (encore :D). Pourquoi tu as rajouté une valeur booléenne upperCase ? Le passage où tu l'utilises je ne comprend pas à  quoi ça sert exactement (même si je sais que ça sert à  mettre un NSString en capitale)

    Pour te répondre Ali, oui mon NSTask je l'ai très bien fait, c'est juste le md5 final qui semblait pas bon du tout.. J'ai bien séparé les arguments par des objets dans une NSArray et non par des espaces

    (J'ai une erreur _MD5 referenced from). Malgré l'import de openssl/md5)


    "upperCase" c'est juste pour utiliser "abcdef" ou "ABCDEF" pour l'hexadécimal
    Effictivement en Release (sans zerolink), il faut ajouter -lcrypto dans les "Other Linker Flags"
  • 20:29 modifié #23
    Okay..
    En tout cas j'ai toujours un BADAuth avec l'URL

    La doc est ici http://www.audioscrobbler.net/development/protocol/
    ça m'énerve parce que si je fait md5(md5(password)+timestamp) dans le terminal et que jle rentre dans l'URL là  ça marche..
  • AliGatorAliGator Membre, Modérateur
    20:29 modifié #24
    dans 1199450148:
    Pour te répondre Ali, oui mon NSTask je l'ai très bien fait, c'est juste le md5 final qui semblait pas bon du tout.. J'ai bien séparé les arguments par des objets dans une NSArray et non par des espaces
    Alors si tu l'as bien fait avec un NSArray, je vois pas pourquoi dans ton stringWithFormat tu as mis des guillemets autour
  • 20:29 modifié #25
    dans 1199454182:

    dans 1199450148:
    Pour te répondre Ali, oui mon NSTask je l'ai très bien fait, c'est juste le md5 final qui semblait pas bon du tout.. J'ai bien séparé les arguments par des objets dans une NSArray et non par des espaces
    Alors si tu l'as bien fait avec un NSArray, je vois pas pourquoi dans ton stringWithFormat tu as mis des guillemets autour


    Parce qu'avec ou sans guillemets ça marche  :o Enfin je viens de m'en rendre compte.
    si tu tapes
    <br />md5 -s &quot;test&quot;<br />md5 -s test<br />
    

    T'obtiens la même chose
  • schlumschlum Membre
    20:29 modifié #26
    dans 1199454552:

    dans 1199454182:

    dans 1199450148:
    Pour te répondre Ali, oui mon NSTask je l'ai très bien fait, c'est juste le md5 final qui semblait pas bon du tout.. J'ai bien séparé les arguments par des objets dans une NSArray et non par des espaces
    Alors si tu l'as bien fait avec un NSArray, je vois pas pourquoi dans ton stringWithFormat tu as mis des guillemets autour


    Parce qu'avec ou sans guillemets ça marche  :o Enfin je viens de m'en rendre compte.
    si tu tapes
    <br />md5 -s &quot;test&quot;<br />md5 -s test<br />
    

    T'obtiens la même chose


    Normal, c'est le principe des arguments en ligne de commande ; ce qui est entre guillemets correspond à  1 argument, même s'il y a des espaces dedans.
    Par contre avec NSTask je crois que si on lui mets, il va les prendre comme faisant partie de l'argument.
  • 20:29 modifié #27
    En tout cas, je suis passé à  ton code Schlum, et ça merde aussi :( Je comprend pas vraiment.

    <br />&nbsp; &nbsp; &nbsp; &nbsp; const char *rep = [password cStringUsingEncoding:NSUTF8StringEncoding];<br />	unsigned int lg = [password lengthOfBytesUsingEncoding:NSUTF8StringEncoding];<br />	unsigned char digest[16];<br />	char hexHash[33];<br />	MD5((const unsigned char*)rep,(unsigned long)lg,digest);<br />	int i,j;<br />	// Optimisable...<br />	for(i=0,j=0;i&lt;16;++i,j+=2)<br />		snprintf(hexHash+j,3,NO?&quot;%02X&quot;:&quot;%02x&quot;,digest[i]);<br />	NSString* md5 = [NSString stringWithUTF8String:hexHash];<br />	<br />	NSTask* task = [[NSTask alloc] init];<br />	[task setLaunchPath:@&quot;/bin/date&quot;];<br />	[task setArguments:[NSArray arrayWithObjects:@&quot;+%s&quot;,nil]];<br />	NSPipe* pipe = [NSPipe pipe];<br />	[task setStandardOutput:pipe];<br />	[task launch];<br />	<br />	NSData* data;<br />	data=[[pipe fileHandleForReading] availableData];<br />	NSString* timestamp = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];<br />	<br />	md5 = [NSString stringWithFormat:@&quot;%@%@&quot;, md5, timestamp];<br />	<br />	rep = [password cStringUsingEncoding:NSUTF8StringEncoding];<br />	lg = [password lengthOfBytesUsingEncoding:NSUTF8StringEncoding];<br />	MD5((const unsigned char*)rep,(unsigned long)lg,digest);<br />	// Optimisable...<br />	for(i=0,j=0;i&lt;16;++i,j+=2)<br />		snprintf(hexHash+j,3,NO?&quot;%02X&quot;:&quot;%02x&quot;,digest[i]);<br />	md5 = [NSString stringWithUTF8String:hexHash];<br />	<br />	<br />	NSString* URLString = [NSString stringWithFormat:@&quot;http://post.audioscrobbler.com/?hs=true&amp;p=1.2&amp;c=osx&amp;v=7.5&amp;u=%@&amp;t=%@&amp;a=%@&quot;,username,timestamp,md5];<br />	NSLog(URLString);<br />	NSURL* url = [NSURL URLWithString:URLString];<br />	NSURLRequest *theRequest=[NSURLRequest requestWithURL:url<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cachePolicy:NSURLRequestUseProtocolCachePolicy<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; timeoutInterval:30.0];<br />	<br />	NSURLConnection* connection = [NSURLConnection connectionWithRequest:theRequest delegate:self];<br /><br /><br />	[timestamp release];<br />
    


    Le truc c'est que le md5 final doit pas être le même que si je le fait sur le terminal. En tout cas l'URL me retourne un BadAuth (voir le lien de la doc plus haut).
  • AliGatorAliGator Membre, Modérateur
    20:29 modifié #28
    dans 1199455406:

    mets ça marche  :o Enfin je viens de m'en rendre compte.
    si tu tapes
    <br />md5 -s &quot;test&quot;<br />md5 -s test<br />
    

    T'obtiens la même chose


    Normal, c'est le principe des arguments en ligne de commande ; ce qui est entre guillemets correspond à  1 argument, même s'il y a des espaces dedans.
    Par contre avec NSTask je crois que si on lui mets, il va les prendre comme faisant partie de l'argument.
    [/quote]Ben oui c'est justement ce que je dis depuis le début !!!
    Evidemment que dans le terminal que tu tapes [tt]md5 -s "test"[/tt] ou [tt]md5 -s test[/tt] ça renvoie les mêmes résultats ! Puisque le shell (bash très certainement) sépare les arguments (en prenant en compte les espaces, les guillemets, les backslashes, les redirections éventuelles, etc.) et qu'une fois qu'il a séparé les arguments et viré les guillemets, il appelle ensuite la tâche comme avec une NSTask, en passant chaque argument séparément comme dans un tableau... donc sans les guillemets, que le shell a enlevé ! Mais avec un appel via NSTask tu appelles directement la tâche sans passer par un shell qui te pré-parserait les arguments et te supprimerait les guillemets ou backslashes.

    C'est pour ça qu'il ne FAUT PAS mettre les guillemets quand pour entourer les arguments quand on appelle une NSTask, même si on les mets quand on fait l'appel dans le terminal. La grande différence se situant donc sur le fait qu'il n'y a pas de shell intermédiaire
  • AliGatorAliGator Membre, Modérateur
    20:29 modifié #29
    dans 1199457351:
    En tout cas, je suis passé à  ton code Schlum, et ça merde aussi :( Je comprend pas vraiment.
    Et moi je capte pas pourquoi tu te compliques autant la vie, en passant par un NSTask aussi pour le calcul du timestamp en plus... et en ayant fait un copier-coller du code que schlum te proposait et qui était sensé être à  mettre dans une catégorie de NSString pour l'utiliser facilement...

    EagleLouk, ou l'art de chercher à  faire compliquer et redondant  :brule:
  • 20:29 modifié #30
    dans 1199457679:

    dans 1199457351:
    En tout cas, je suis passé à  ton code Schlum, et ça merde aussi :( Je comprend pas vraiment.
    Et moi je capte pas pourquoi tu te compliques autant la vie, en passant par un NSTask aussi pour le calcul du timestamp en plus... et en ayant fait un copier-coller du code que schlum te proposait et qui était sensé être à  mettre dans une catégorie de NSString pour l'utiliser facilement...

    EagleLouk, ou l'art de chercher à  faire compliquer et redondant  :brule:


    C'est pour tester au départ c'est pour ça :p
    Après je ferais une classe pour car je dois l'utiliser dans d'autres classes !
  • janvier 2008 modifié #31
    C'est bien le md5 de md5pass+timestamp qui est erronné. Avec le terminal j'obtiens quelque chose de différent avec le même timestamp..
    En fait au final j'obtiens le même md5 que celui du mot de passe.
Connectez-vous ou Inscrivez-vous pour répondre.