Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

[RubyCocoa] NSString vs ruby string

13 réponses
Avatar
unbewusst
j'ai un petit probl=E8me dans une application RubyCocoa avec les
strings.

elles ont deux origines :

- 1 - Dir.glob(...) c=F4t=E9 Ruby, les strings de ces pathes n'ont pas de
probl=E8me m=EAme si elles comportent des accents et des espaces.

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

/Volumes/EMTEC KEY
--------------^---

bien s=FBr, c=F4t=E9 ruby je les transforme en strings ruby :

file[ 0 ].to_s

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

.gsub( / /, '\ ')

c=E0d 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 ?

10 réponses

1 2
Avatar
luc
unbewusst wrote:

mais ce n'est pas suffisant...


Ce n'est pas suffisant pour faire quoi ?

--
Luc Heinrich

Avatar
unbewusst
On 7 sep, 14:37, (Luc Heinrich) wrote:
unbewusst wrote:
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


Avatar
unbewusst
On 7 sep, 15:53, unbewusst wrote:
On 7 sep, 14:37, (Luc Heinrich) wrote:

unbewusst wrote:
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)



Avatar
luc
unbewusst wrote:

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

Avatar
Erwan David
unbewusst écrivait :

On 7 sep, 14:37, (Luc Heinrich) wrote:
unbewusst wrote:
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



Avatar
unbewusst
On 7 sep, 16:34, Erwan David wrote:
unbewusst écrivait :

On 7 sep, 14:37, (Luc Heinrich) wrote:
unbewusst wrote:
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.




Avatar
unbewusst
On 7 sep, 16:10, (Luc Heinrich) wrote:
unbewusst wrote:
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


Avatar
luc
unbewusst wrote:

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

Avatar
unbewusst
On 8 sep, 11:05, (Luc Heinrich) wrote:
unbewusst wrote:
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


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

unbewusst wrote:
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 ;-)



1 2