[RubyCocoa] NSString vs ruby string

Le
unbewusst
j'ai un petit problème dans une application RubyCocoa avec les
strings.

elles ont deux origines :

- 1 - Dir.glob() côté Ruby, les strings de ces pathes n'ont pas de
problème même si elles comportent des accents et des espaces.

- 2 - File/Folder Chooser de Cocoa là, j'ai un pb avec les NSString
qui comportent une espace comme dans :

/Volumes/EMTEC KEY
--^

bien sûr, côté ruby je les transforme en strings ruby :

file[ 0 ].to_s

mais ce n'est pas suffisant il faut que j'ajoute :

.gsub( / /, ' ')

càd que "j'escape" les espaces des pathes obtenus par un File/Folder
Chooser.

est-ce normal ?

c'est du MacOS Roman ce qui sort d'un File Chooser ?
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 2
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
luc
Le #501651
unbewusst
mais ce n'est pas suffisant...


Ce n'est pas suffisant pour faire quoi ?

--
Luc Heinrich

unbewusst
Le #501650
On 7 sep, 14:37, (Luc Heinrich) wrote:
unbewusst
mais ce n'est pas suffisant...


Ce n'est pas suffisant pour faire quoi ?

--
Luc Heinrich




ben je dois ajouter .gsub(/ /, ' ')

afin que les strings de provenance file/Folder Chooser passent
correctement quand j'appelle rsync par exemple.

si non j'a


unbewusst
Le #501649
On 7 sep, 15:53, unbewusst
On 7 sep, 14:37, (Luc Heinrich) wrote:

unbewusst
mais ce n'est pas suffisant...


Ce n'est pas suffisant pour faire quoi ?

--
Luc Heinrich


ben je dois ajouter .gsub(/ /, ' ')

afin que les strings de provenance file/Folder Chooser passent
correctement quand j'appelle rsync par exemple.

si non j'a




(coupure je suis sur pécé...)


si non j'ai droit à un message d'erreur :

/Volumes/EMTEC file or directory doesn't exists.

ce qui est vrai car celle qui existe est :

/Volumes/EMTEC KEY avec donc une espace entre EMTEC et KEY.

ce que je trouve curieux est que j'ai d'autres folder qui ont des
blancs dans leur nom, y compris d'ailleurs des caractères accentués,
mais ceux-ci sont obtenus par un Dir.glob(...) de ruby et ça ne pose
pas de pb quand je file le path tel quel à rsync...

j'en ai, peut-être abusivement, conclus que le traitement, ou
l'encodage, des caractères n'est pas le même côté Cocoa que côt é
ruby ???

j'avais essayé de mettre des "" autour de mes paths, pour les
"protéger" là du coup j'ai un problème ailleurs, au niveau de
l'executeWithPrivileges... ( Carbon si je ne m'abuse)



luc
Le #501648
unbewusst
ben je dois ajouter .gsub(/ /, ' ')


Oui merci tu l'as déjà dit.

afin que les strings de provenance file/Folder Chooser passent
correctement quand j'appelle rsync par exemple.


Mais encore ?

--
Luc Heinrich

Erwan David
Le #501647
unbewusst
On 7 sep, 14:37, (Luc Heinrich) wrote:
unbewusst
mais ce n'est pas suffisant...


Ce n'est pas suffisant pour faire quoi ?

--
Luc Heinrich




ben je dois ajouter .gsub(/ /, ' ')

afin que les strings de provenance file/Folder Chooser passent
correctement quand j'appelle rsync par exemple.


À te lire j'ai plutot l'impression que tes chaînes sont bonnes (elles
donnent le nom du répertoire). Par contre tu sembles lancer rsync par
l'intermédiaire d'un shell.
Et c'est pour le shell qu'il faut un avant l'espace, parceque c'est le
shell qui interprète l'espace.

--
Erwan



unbewusst
Le #501646
On 7 sep, 16:34, Erwan David
unbewusst
On 7 sep, 14:37, (Luc Heinrich) wrote:
unbewusst
mais ce n'est pas suffisant...


Ce n'est pas suffisant pour faire quoi ?

--
Luc Heinrich


ben je dois ajouter .gsub(/ /, ' ')

afin que les strings de provenance file/Folder Chooser passent
correctement quand j'appelle rsync par exemple.


À te lire j'ai plutot l'impression que tes chaînes sont bonnes (elles
donnent le nom du répertoire). Par contre tu sembles lancer rsync par
l'intermédiaire d'un shell.
Et c'est pour le shell qu'il faut un avant l'espace, parceque c'est le
shell qui interprète l'espace.

--
Erwan



???

ben je lance rsync par l'intermédiaire d'un script ruby (mon
application est rubycocoa).

ce que je trouve étrange est que les strings de provenance ruby (par
Dir.glob(...) ) même si elles comportent des espaces passent tel
quelles.

celles de provenance File/Folder Chooser nécessitent un devant les
espaces.

alors de plus les arguments pour rsync passent par une moulinette ( C
ext to Ruby ) qui opère de deux manières :

- soit l'utilisateur a besoin d'une authetification/authorization pour
accéder aux privilèges root et là je passe mes arguments à une
fonction Carbon "executeWithPrivileges" (de mémoire) qui accepte les
arguments pour rsync sous forme d'un tableau C terminé par un NULL du
genre :

executeWithPrivileges( privilegesRef, "path_to_rsync", { "arg1",
"arg2", ..., "argn", NULL} ) (tjs de mémoire) ;

- soit l'utilisateur n'a pas besoin de privilège est l'extension C
pour Ruby fait un popen et retourne (comme dans le cas précédent) le
fileno du pipe. MAIS, dans ce cas le mode de passage des arguments est
différent, je fais une concaténation des arguments passés en
intercallant des espaces entre chaque argument du genre (avec strcat
en C donc) l'appel à rsync est donc, dans ce cas, du genre :

fd = popen("/path/to/rsync les args concaténés", "r") (tjs de mémoi re)

bon, je suis sur que si nje lance rsync directement par ruby (donc
sans privilèges root et sans extension ruby) par un IO.popen les
strings ruby (Dir.glob) passent très bien, de mémoire j'en ai une,
dans mon répertoire ~/Documents, du genre "Données Utilisateur
Appleworks" qui enregistrée dans un fichier de préférence (yaml) est
écrite sans devant les espaces et avec les accents ajoutés après le
caractère comme dans :
Donne' es Utilisateur Appleworks

et ça ça marche très bien.




unbewusst
Le #501645
On 7 sep, 16:10, (Luc Heinrich) wrote:
unbewusst
ben je dois ajouter .gsub(/ /, ' ')


Oui merci tu l'as déjà dit.

afin que les strings de provenance file/Folder Chooser passent
correctement quand j'appelle rsync par exemple.


Mais encore ?



en pratique j'ai un path, celui de la clé USB qui est :

/Volumes/EMTEC KEY

ce path est obtenu par File/Folder Chooser.

si j'envoie ce path sur rsync tel quel, rsync râle car il ne trouve
pas le répertoire /Volumes/EMTEC, normal il n'existe pas, donc ça veut
dire, amha, que le blanc n'est pas "escapé" par <NSArray de retour du
File chooser>[ 0 ].to_s


luc
Le #501644
unbewusst
si j'envoie ce path sur rsync tel quel


*COMMENT* ? Du code! Du concret! De l'exemple! C'est impossible de
t'aider uniquement à partir de tes pseudo explications obscures en
pseudo français!

--
Luc Heinrich

unbewusst
Le #501643
On 8 sep, 11:05, (Luc Heinrich) wrote:
unbewusst
si j'envoie ce path sur rsync tel quel


*COMMENT* ? Du code! Du concret! De l'exemple! C'est impossible de
t'aider uniquement à partir de tes pseudo explications obscures en
pseudo français!

--
Luc Heinrich




OK, je vois, je fais ça demain, je ne suis pas connecté en direct.

A +, bon dimanche !

Yvon


unbewusst
Le #501642
On 9 sep, 15:46, unbewusst
On 8 sep, 11:05, (Luc Heinrich) wrote:

unbewusst
si j'envoie ce path sur rsync tel quel


*COMMENT* ? Du code! Du concret! De l'exemple! C'est impossible de
t'aider uniquement à partir de tes pseudo explications obscures en
pseudo français!

--
Luc Heinrich


OK, je vois, je fais ça demain, je ne suis pas connecté en dire ct.

A +, bon dimanche !

Yvon


voila le toutim :

Choix d'un répertoire :
+---------------------+


def chooseUsbkey( notification )
oPanel = NSOpenPanel.openPanel
[...]
buttonClicked = oPanel.runModal
if buttonClicked == NSOKButton
files = oPanel.filenames
@usbkey.setStringValue( files[ 0 ].to_s.gsub(/ /, ' ') )
end
end

@usbkey est un NSTextField

exemple de répertoire : /Volumes/EMTEC KEY

Dans un de ses répertoire, un script ruby obtient les sous-
répertoires :

def getFolders( path )
fs = [ ]
Dir.glob( "#{path}/*").each { |f|
if FileTest.directory?(f)
fs << File.basename(f)
end
}
return fs
end

exemples de sous répertoires :
/Users/yt/Documents/Données utilisateur AppleWorks
/Users/yt/Documents/Données utilisateurs Microsoft


ces deux sous-répertoires seront synchronisés avec :

/Volumes/EMTEC KEY/Documents/Données utilisateur AppleWorks
/Volumes/EMTEC KEY/Documents/Données utilisateurs Microsoft

lesquels sont créés par: FileUtils.mkdir_p( "#{i.path}/#{ii.name }" )

construction de la commande "rsync" (j'utilise la version rsync de
Boyd pour HFS+)

les options :
optionsAry << ( ( @verbose.state.to_i === 1 )? "-av" : "-a" )
optionsAry << "--progress" if @progress.state.to_i === 1
optionsAry << "--delete" if @delete.state.to_i === 1
optionsAry << "--dry-run" if @dryrun.state.to_i === 1
optionsAry << "--eahfs"

les excludes (éventuels) :

i.items.each {|ii|
if ii.enabled == false
excludes << "--exclude=#{ii.name}/"
end
}


pour finalement avoir l'Array d'options :

options = optionsAry + excludes + [ "#{i.path}", "#{@root.path}" ]

l'éxécution de rsync :

fd = auth.exec( "#{RSYNC}", options )
IO.for_fd( fd ).each do | f |
f.each_line { | l | log l }
end

avec auth, une instance de :

auth = ROSXAuth.new @isRootPrivileges

avec @isRootPrivileges étant un flag indiquant si l'utilisateur
souhaite synchroniser avec les privilèges root ou non.


donc ROSXAuth est une classe qui fait l'objet d'une extension C pour
ruby.

par défaut, la classe suppose que l'utilisateur souhaite une
autentification/autorisation.




dans le cas où une autentification/autorisation est demandée le C (du
point de vue des strings) se résume à :


int executeWithPrivileges( AuthorizationRef *authRef, char
*myToolPath, char **myArguments )
{
OSStatus myStatus;
FILE *comPipe = NULL;
int fd;

AuthorizationFlags myFlags = kAuthorizationFlagDefaults;

myStatus = AuthorizationExecuteWithPrivileges( *authRef, myToolPath,
myFlags, myArguments, &comPipe );

fd = fileno( comPipe );

if ( myStatus )
{
fprintf( stderr, "%s: Status: %ldn", __func__, myStatus );
return EXIT_FAILURE;
}

return fd;
}


avec authRef un pointeur sur l'AuthorizationRef obtenue ;
myToolPath le path absolu de rsync ;
myArguments sont grosso-modo les options vues justes au-dessus et
extraites des VALUEs ruby :

VALUE m_exec_with_priv( VALUE self, VALUE toolPath, VALUE args ) {
char *cToolPath;
int i, len, fd;

VALUE is_auth = rb_iv_get( self, "@isAuthorized" );
if ( is_auth == Qfalse )
return Qnil;

cToolPath = calloc( MAX_PATH, 1 );
if( cToolPath == NULL )
{
[...] gestion d'une erreur
}
strcpy( cToolPath, StringValuePtr( toolPath ) );

if ( TYPE( args ) == T_NIL )
{
fd = executeWithPrivileges( authRef, cToolPath, NULL );
}
else if ( TYPE( args ) == T_ARRAY )
{
len = RARRAY( args )->len;
char *cargs[ len ];
i = 0;
while( i < len )
{
if ( TYPE( RARRAY( args )->ptr[ i ] ) == T_STRING )
{
cargs[ i ] = calloc( 255, 1 );
if( cargs[ i ] == NULL )
{
[...] gestion d'une erreur
}
cargs[ i ] = strdup( RSTRING( RARRAY( args )->ptr[i] )->ptr );
}
else
{
[...] gestion d'une erreur
}
i++;
}
cargs[ i ] = NULL;
fd = executeWithPrivileges( authRef, cToolPath, cargs );
}
else
{
[...] gestion d'une erreur
}

if ( fd == EXIT_FAILURE )
return Qnil;

return INT2FIX( fd );
}


donc à l'Array/Ruby options correspond ici le tableau C cargs qui ne
comporte qu'un élément de plus à NULL, pour des raisons de t est de fin
d'Array.





dans le cas où il n'y a pas besoin des privilèges root, le C (du point
de vue des strings) se résume à :

on utilise fd = executeWithoutPrivileges( cToolPath, cargs ); avec :


int executeWithoutPrivileges( char *myToolPath, char **myArguments )
{
FILE *comPipe = NULL;
int i, fd;
char *cmd;

cmd = calloc( LINE_MAX, 1 );
if( cmd == NULL )
{
[...] gestion d'une erreur
}
strcpy( cmd, myToolPath );

i = 0;
while( myArguments[ i ] != NULL)
{
strcat( cmd, " " );
strcat( cmd, myArguments[ i ] );
i++;
}

if ( !( comPipe = popen( cmd, "r" ) ) )
{
[...] gestion d'une erreur
}

fd = fileno( comPipe );

return fd;
}

là la chaîne d'arguments est batie par concaténation de *myT oolPath et
des **myArguments avec un " " comme séparateur :

strcat( cmd, " " );
strcat( cmd, myArguments[ i ] );


voilà, c'est tout ;-)



Publicité
Poster une réponse
Anonyme