OVH Cloud OVH Cloud

[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 ?

3 réponses

1 2
Avatar
luc
unbewusst wrote:

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


oPanel.filenames retourne un tableau de NSString non ? Et si usbkey est
un NSTextField, pourquoi faire un to_s ? De plus, le gsub est prématuré
ici, l'utilisateur n'a pas à voir la cuisine interne. On va partir du
principe qu'on en a pas besoin.

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


La même chose en une ligne:

def getFolders(path)
Dir.glob("#{path}/*").find_all { |f| File.directory?(f) }
end

les excludes (éventuels) :

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


En plus court et plus Ruby:

excludes = i.items.collect do |ii|
"--exclude="#{ii.name}" unless ii.enabled
end

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


Tu fais la même faute tout le temps: i.path est DEJA une string, et je
parie que @root.path l'est aussi, alors POURQUOI faire une interpolation
?!???

options = optionsAry + excludes + [ i.path, @root.path ]

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


La doc dit que "The arguments you pass in the arguments parameter are
relayed to the new process's argv parameter" ce qui sous entendrait donc
qu'il n'y a PAS besoin d'escaper les espaces...

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 );
}


man strdup:

"The strdup() function allocates sufficient memory for a copy of the
string str, does the copy, and returns a pointer to it"

Ton cargs[ i ] = calloc( 255, 1 ) ne sert donc à rien et n'est qu'un
gros leak.

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 );


Gné ? Et là il quoi il sert le strcpy ? Non seulement tu aimes bien
faire des choses de la manière la plus compliquée possible, mais en plus
tu aimes bien gaspiller la RAM ? :)

voilà, c'est tout ;-)


Eh ben y a du boulot... O:)

--
Luc Heinrich

Avatar
unbewusst
On 10 sep, 10:45, (Luc Heinrich) wrote:

Eh ben y a du boulot... O:)



OK, yaduboulot )))

merci beaucoup, j'ai modifié ce que tu m'as donné dans ton précédent
message, + une simplification perso :

dans mon fichier "rosxauth.c" (le fichier C ext to ruby) :

VALUE m_exec_without_priv( VALUE self, VALUE toolPath, VALUE args ) {
char *cmd;
int i, len, fd;

cmd = calloc( MAX_PATH, 1 );
if( cmd == NULL )
{
fprintf( stderr, "%s: calloc failed allocating memory for "cmd
"!n", __func__ );
return Qnil;
}
strcpy( cmd, StringValuePtr( toolPath ) );

if ( TYPE( args ) == T_NIL )
{
fd = executeWithoutPrivileges( cmd );
}
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 )
{
strcat( cmd, " " );
strcat( cmd, RSTRING( RARRAY( args )->ptr[i] )->ptr );
}
else
{
fprintf( stderr, "%s: wrong argument type "cargs[ %d ]" is
not a string!n", __func__, i );
return Qnil;
}
i++;
}
fd = executeWithoutPrivileges( cmd );
}
else
{
fprintf( stderr, "%s: TYPE( args ) = NOT A VALID VALUE ( %d )n",
__func__, TYPE( args ) );
rb_raise(rb_eTypeError, "not valid value");
return Qnil;
}

if ( fd == EXIT_FAILURE )
return Qnil;

return INT2FIX( fd );
}


donc dans le fichier "osxauth.c" j'ai modifié "" accordingly :

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

if ( !( comPipe = popen( cmd, "r" ) ) )
{
fprintf( stderr, "Unable to popen "%s" :n%sn", cmd,
strerror( errno ) );
//perror( "popen" );
return EXIT_FAILURE;
}

fd = fileno( comPipe );

return fd;
}


RESULTAT des courses :

quand j'utilise les privileges root, pas de pb, tout se passe bien.

par contre quand je n'utilise pas les privilèges root, je reviens au
pb de départ, rsync (la version Boyd) me dit :

link_stat "/Volumes/EMTEC" failed: No such file or directory


donc là, il y a bien un pb avec l'espace entre EMTEC et KEY...

Yvon

Avatar
luc
unbewusst wrote:

par contre quand je n'utilise pas les privilèges root, je reviens au
pb de départ...


Et pour cause.

man popen:
"The command argument is a pointer to a null-terminated string
containing a shell command line. This command is passed to /bin/sh
using the -c flag; interpretation, if any, is performed by the shell."

Ce qui veut dire que dans ce cas tu *dois* escaper la commande et les
paramètres ou les mettre entre "". Perso je ferais ça du coté Ruby, ton
code C est toujours aussi dangeureux. Tu en fais beaucoup trop du coté
C.

--
Luc Heinrich

1 2