Données via URL
Bonjour,
j'aimerai pouvoir envoyer une donnée puis la récupérer via une URL.
Le problème est que je n'arrive pas récupérer le NSData de l'URL.
Par exemple :
test://< 04bc58de 04bc58de 04bc58de 04bc58de >
Et j'aimerai récupérer "< 04bc58de 04bc58de 04bc58de 04bc58de >" qui est la donnée (NSData)
Je sais pas si ça se fait mais bon.. ça serait cool.
En fait mon application permet de créer des dossiers persos (NSDictionary), donc j'aimerai bien inclure une sorte de partage de dossiers via URL.
j'aimerai pouvoir envoyer une donnée puis la récupérer via une URL.
Le problème est que je n'arrive pas récupérer le NSData de l'URL.
Par exemple :
test://< 04bc58de 04bc58de 04bc58de 04bc58de >
Et j'aimerai récupérer "< 04bc58de 04bc58de 04bc58de 04bc58de >" qui est la donnée (NSData)
Je sais pas si ça se fait mais bon.. ça serait cool.
En fait mon application permet de créer des dossiers persos (NSDictionary), donc j'aimerai bien inclure une sorte de partage de dossiers via URL.
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Dans mon application, l'utilisateur peut créer des dossiers personnalisés (dans l'application). Le truc ça sera de pouvoir partager ses dossiers via une simple URL générée par mon application.
Chaque dossier est un NSDictionary. Donc quand je choisis de partager le dossier, l'application me donnerait une url comme ceci : "MonApplication://DONNEES_DU_NSDICTIONARY"
Lorsque l'utilisateur cliquera sur ce lien, mon application s'ouvre, et là je décode "DONNEES_DU_NSDICTIONARY" pour ensuite ajouter le dossier à sa liste.
Je ne suis pas persuadé que ton approche soit la bonne, mais bon j'imagine que tu ne peux pas simplement donner des identifiants à tes dossiers virtuels, le but étant de les partager entre ordinateurs différents, et que l'URL "explique" en tout point à ton application comment créer le dossier virtuel et son contenu...
Il faut donc que tu sérialises tes données de manière à obtenir une chaà®ne de caractères qui respecte la RFC 2396 entre autres, pour pouvoir utiliser cette chaà®ne comme une URL.
Le plus simple est d'obtenir une représentation en NSData de ton dictionnaire, puis d'exprimer cette représentation en hexadécimal, pour être sûr de ne pas avoir d'espace ni de caractère invalide, et de construire alors ton URL du genre [tt]monApplication://createFolder/04ae7fd3c7e6db8a...[/tt]
Note que la façon dont tu l'as noté plus haut, même si ça ressemble à un encodage hexadecimal, ce n'est que le [tt]description[/tt] de ton NSData... qui contient "<NSData" et ">" en trop, et surtout plein d'espaces
Mais le risque c'est alors de voir tes NSData, une fois représentés en hexadécimal, dépasser la longueur max des URL (256 caractères, je crois ?)
Et de toute façon il y a des chances que tu te heurtes à ce problème de taille maxi des URLs. Même si tu utilises une autre sérialisation, tu trouveras toujours des NSData qui, une fois sérialisées en des caractères se conformant à la RFC 2396 de syntaxe des URLs, risquent de dépasser la taille max.
Donc faut peut-être se reposer la question de la faisabilité de la chose... déjà pour créer une URL valide. Parce que sans URL valide, point de décodage d'URL ensuite et donc point de récupération des NSData reconstruites après désérialisation de l'URL
Par contre, tu peux le faire à la GET : test://addr?v=<data>
Je pense avoir trouvé une solution pour mon Application.
Le plus important pour un dossier perso c'est le nom et ce qu'il contient.
Mon application, vous la connaissez sûrement déjà , permet de référencer des freewares pour Mac OS X et de les faire découvrir aux utilisateurs.
Donc il y a une Array qui contient les applications choisis par l'utilisateur dans chaque dossier.
Donc en gros :
{
<key>Name</key>
<string>LeNom</key>
<key>Applications</key>
<array>
<string>App1</string>
<string>App2</string>
<string>App3</string>
<string>App4</string>
</array>
}
(On s'en fiche si ma représentation est pas bonne, c'est pour que vous compreniez mieux comment c'est foutu).
L'avantage est que je fonctionne aussi par ID de logiciels.
Dans ce cas je pourrais peut-être envoyé l'URL comme ceci :
MonApp://LeNom/ID1.ID2.ID3.ID4...
Pour les URLs, je ne savait pas qu'elles étaient limitées, du moins j'y avais jamais vraiment pensé. Mais dans ce cas, si elles sont limitées à 256 caractères comme tu le dis Alli, je peux proposer à l'utilisateur d'enregistrer le groupe sous forme d'un fichier à envoyer aux ami(es) dans ce cas là .
J'autorise aussi la création de dossiers intelligents, qui font donc un trie automatique de tous les logiciels de la base de données en fonction des critères choisis.
Et dans ce cas là je pourrais faire :
MonApp://LeNomDuSmartGroup/Option1:critere1.critere2.critere3/Option2.......
On peut créer 5 options maximales et pareil, si ça dépasse 256 caractères je propose d'enregistrer dans un fichier.
C'est carrément possible puisque je l'ai déjà fait. Il faut utiliser les AppleEvents et enregistrer ton appli pour qu'elle ouvre les url commençant par test://
1. Dans le awakeFromNib du delegate de NSApplication:
2. Dans le même delegate:
3. Dans le Info.plist , ajouter ceci pour qu'un clic sur l'URL ouvre ton appli:
4. Quand c'est prêt, annoncer la mise à jour à tous ceux qui pensaient kecépapossibe !
Tu transformes ton NSDictionary en NSData.
Ce NSData te sert (du moins sa représentation) d'url.
Ensuite, quand ton appli reçoit l'appel de l'url, tu veux récupérer l'adresse pour la retransformer en NSData puis NSDictionary.
Est ce ça ?
Quant à la taille d'une url, cela varie en fait en fonction du client.
Formellement, la taille est de 1024. Mais il est conseillé de ne pas dépasser les 255 car certains vieux clients ne pourraient pas traiter ce qui se trouve au delà . Pourtant les navigateurs récents proposent plus.
.
C'est exactement ce que je veux faire. Tout comme l'a suggéré Laurris. C'est ce que j'avais fait au départ.
En fait Laurris, pour reprendre ce que je disais, ça ne marche pas car en fait lorsque je récupère la représentation d'un NSData, j'obtiens bien < eD9b14cf etc.... >
Pour en faire une URL disons "correcte" je dois eviter les espace. Donc au lieu d'utiliser "stringByAddingPercentEspacesUsingEncoding:" j'ai choisis d'analyser mon URL avec espace et de les enlever.
Ainsi ça donnait : xtastes://eD9b14cfetc....
Quand je récupère l'URL, je la reformate et j'obtiens bien < eD9b14cf etc... > comme au départ.
Sauf que évidemment, ça peut pas être aussi simple que ça et impossible de dire que ce que je récupère est un NSData. Donc NSDictionary* group = [NSUnarchiver unarchiveObjectWithData:LeDataReformaté]; ne marche pas
En fait ta question n'a rien à voir avec les url ou la façon de les traiter. C'est comment faire pour encoder/decoder un NSData en NSString. Sur ce point de plus experts que moi pourront te répondre.
Mais je ne saisis pas pourquoi tu n'utilise pas stringByAddingPercentEspacesUsingEncoding: sur la description du dictionary. Ensuite dans le handler tu décodes l'URL en string > data > dictionary.
A mon avis la limitation de 256 n'a pas de sens dans ton cas puisque le navigateur n'interprète pas l'url, il la passe direct à l' NSAppleEventManager. Script Editor a dans 10.4 la possibilité d'ouvrir des scripts à partir d'URL et la longueur des scripts atteint plus de 256 char sans problème.
C'est tout à fait ce à quoi j'ai pensé !
Et donc ce que je n'ai pas réussi à faire malgré toute une après midi passé dessus.
Comme ça un NSData de longueur 30 qui auraà®t nécessité 60 caractères pour être représenté en hexa, ne nécessitera que 40 caractères dans sa représentation base64.
Donc en somme ce que je te conseille, c'est de créer une catégorie de NSData qui va te rajouter la méthode [tt]NSString * encodeBase64[/tt] et une catégorie de NSString qui va te rajouter la méthode [tt]NSData * decodeBase64[/tt]. Ainsi tu pourras, à partir de ton NSData (représentation sérialisée de ton NSDictionary), obtenir une NSString (représentation en base64 de tes données) et l'utiliser dans ton URL, et dans l'autre sens lors de la récupération de l'URL, tu pourras retransformer ton NSString en NSData (puis en NSDictionary ou ce que tu veux).
Pour encoder/décoder en base64, tu peux utiliser libcrypto (OpenSSL) qui contient des méthodes pour faire ça, ça t'évitera de tout recoder. Le code a déjà été pondu sur CocoaDev : regarde vers la fin quand ils proposent d'utiliser libssl directement ("You can using libcrypto, part of OpenSSL, to do this directly without spawning a task:")
En plus c'est mieux que la représentation hexa car d'une part ça prend moins de place une fois encodé, mais en plus le code est déjà tout fait :P alors que pour la représentation hexa sinon tu vas devoir la faire toi-même (ceci dit entre nous c'est pas sorcier comme dit schlum)
En tout cas j'ai tout vérifié, ça marche très bien et j'obtiens bien mon dossier décodé au final :
Si ça en branche quelques uns je pourrai en faire un framework et le mettre sur les ressources d'Objective-Cocoa ?
Petite remarque, j'ai du utiliser
à la place de
car "deprecated in Mac OS X 10.4".
Mon appli sera Leopard uniquement donc ça va ^^
C'est pas un drame d'utiliser la UTF8String au lieu de la cString, vu que ce que tu récupères ce sont des caractères qui sont normalement le résultat d'un encodage Base64 : donc ils ne contiennent que [A-Za-z0-9/+=] qui sont des caractères ASCII-7bits : autrement dit ils ont la même représentation en UTF8 qu'en "caractères (octets) bruts".
Sinon pour ton information BIO ça n'a rien à voir avec l'agriculture biologique mais ce sont des structures utilisées en OpenSSL pour faire de l'abstraction sur les entrées/sorties, d'où le "IO" (Input/Output) de "BIO". Ce qui est fort avec ce mécanisme, c'est qu'on peut créer un BIO à partir d'un fichier ou d'une zone mémoire (ici c'est notre cas) ou un socket réseau ou autre, ça s'utilise pareil... Mais surtout ensuite on peut créer une chaà®ne de filtres (BIO_f_...) qui vont filtrer les données lues et/ou écrites de manière transparente.
Du coup tu construit une "chaà®ne BIO" qui inclut un filtre base64 et automatiquement ça va encoder en base64 lors de la lecture, décoder lors de l'écriture, et ce de façon transparente...
Enfin bref, même si ça semble bizarroà¯de comme code au premier abord, au final c'est assez bien foutu (pour du code C donc non encapsulé objet :P). Juste pour ta culture : la page man qui va bien ;D
Oh, et petite précision, dans le lien vers CocoaDev ils proposent de rajouter 2 méthodes, une avec un paramètre et l'autre sans. par défaut la valeur du paramètre est à YES, ce qui fait qu'il rajoute des sauts de ligne régulièrement dans le résultat de l'encodage base64.
Ceci est pratique si tu veux encoder un long fichier (par exemple du genre le mode "uuencode") en base64 pour le formatter*, mais dans ton cas, à savoir pour l'utiliser dans une URL, c'est évidemment à proscrire : il faut bien sûr passer NO comme paramètre !
*pour la petite histoire, c'est surtout historique, je me rappelle du format uuencode utilisé pour l'envoi de pièces jointes par mail/newgroups, où les données binaires (les fichiers en PJ) étaient envoyées sous forme uuencodée, c-à -d encodées en base64 puis envoyées comme du texte normal dans le mail... ou comment envoyer des fichiers via un système prévu à l'origine uniquement pour le texte
J'avais bien mis NO pour les espaces ça au moins j'avais compris ;D