Remote API, and apache server.

Hey, stupid question.

Does ReadParse() not know how to deal with multiple arguments with the same name? I’ve tried this using a select multiple, and simply check boxes with name=nodes. I need to be able to submit multiple nodes at the same time (node id’s to be exact), and from what I’m reading, the form submission should go like this:

remote_api.cgi?function=add_replicas&nodes=id1id2id3

This isn’t happening though. Whatever hte last value for nodes is overwrites the previous, so I get the very last one every time. I’ve tried doing @nodes = split(//,$in{nodes}), which I’m certain I’ve been able to do before, but for whatever reason it doesn’t work. The value of $in{nodes} is a string and that string in the above example would be id3, rather than id1id2id3. I could always go outside the API and parse STDIN myself, but I’d prefer to use webmin’s API and not reinvent the wheel.

Any idea what I might be doing wrong?

Hi Tony,
The ReadParse function has a pretty silly way of handling multiple parameters with the same name - it just puts them into a single value in the %in hash, separated by null bytes (). So if you had a form like :

<input type=checkbox name=foo value=1> One
<input type=checkbox name=foo value=2> Two

You could get the selected checkbox values with :

&ReadParse();
@checked = split(//, $in{‘foo’});

I’ve figured this much out - without the , I’m passing the array itself. With the backslash, I’m passing an array reference.

In either case, the actual values within the array aren’t getting through. If I pass @nodes, attempting to print is null or undef. If I pass @nodes, it’s populated with an array reference. Attempting to dereference it gets me null or undefined @{$_[[0]]).

So…yeah. What on earth. I’m passing hashes as params all over the place. I have no idea what I’m doing that is giving me such headaches using an array.

I am about ready to rip my hair out now. :stuck_out_tongue:

Fixed the form input issue. Values are getting passed to what I have named remote_api.cgi. This doesn’t return a full html document, rather just bare http headers, and some text that updates the page in real time. This works as well.

The problem is something stupidly simple that I can’t seem to get working.

I make a sub named add_nodes_as_replicas, which takes an array as an argument. I thought I had this working when I did it on the command line, but it has since stopped.

I pass an array with node id’s, and it is supposed to either return 0 for success, or a string with an error message. Again, dead simple.

Well…not when I’m involved apparently. :stuck_out_tongue: First thing I do is run a test to make sure I got parameters to begin with, so I did:

    if(! @_){
            return($text{'no_nodes_for_addition'});
    }
    else{

It passes that condition and goes into the main routine.

            my @nodes_for_addition = @{ $_[[0]] };

            if(! @nodes_for_addition){

return ("Some useful debugging thing here");

This is where I get tripped up. @nodes_for_addition isn’t getting populated, and I’m afraid it is because of the way I’m passing that array, but I’m not sure. I’m calling it using this syntax: add_nodes_as_replicas(@nodes);

You have to escape the at sign in order to get it to pass at all. If I iterate through @, I can confirm that $[[0]] did get populated, and if I attempt to print $_[[0]], I get this:

ARRAY(0x804dd78)

So it is populated with an array (or at least an array reference?), so then I thought I’d get smart and use @{ $[[0]] }, which again makes sense, but that comes back either undef or null (can’t tell which). Logic tells me that it should print out a space-separated list of the node id’s. I also tried to get smart and do scalar(@{ $[[0]]}), hoping it would give me a count of the number of nodes passed, again, it does not. If I go back to the original routing (prior to passing the array to add_nodes_as_replicas) and print @nodes, I get a space separated list, and scalar(@nodes) does indeed give me a count of the number of id’s in the array.

Which brings me to my conundrum - am I using poor syntax when passing the array as an argument to add_nodes_as_replicas(@array), or am I trying to reference it incorrectly? Perhaps I should be using a pointer in there? I’ve even tried @{ $_[[0]] }->[[0]] in an attempt to get at the first element, no luck. :frowning:

Any ideas?

Could you post the function and the call to it? It is probably a simple mismatch between the format passed and expected …

If you want to pass an array, you can use code like :

my_function(@array);

sub my_function
{
my ($arrayref) = @_;
foreach my $e (@$arrayref) {
print "array element $en";
}
}

All I was suggesting was maybe doing this:

if(re($_[[0]]) eq ‘HASH’){
# Do it that way.
}
else(
# Do it the same way you always have.
}

:smiley:

Oh well, picking nits.

Hey Jamie? I started to make a change in web-lib-funcs.pl what would clean up much of what I’m doing, not break anything backwards, and make for much more intuitive code.

For example, in my module’s index.cgi, I have this:

&header($text{‘module_title’}, “”, “”, “”, “”, “”, “”, $custom_headers);

What I was thinking was to modify sub header{}. Right now you kind of interpolate checking for values passed with generating the headers. What I would do (and have backed off of, since that’s really your baby and not mine), is to instead use static variables and render the headers in one shot. At the top of the routine, check to see whether $_[[0]] is a hash or not. If not, use assignments as you have in the past, ie:

my $title = $[[0]];
my $image = $
[[1]];
my $help = $[[2]] if($[[2]]);
my $config = $[[3]] if($[[3]]);

etc.

if $_[[0]] is a hash however, then we can make for much more readable code. I could do the above like this:

&header({
title => $text{‘module_title’},
header => $custom_headers,
});

Then in your routine, you assign as such:

my(%config) = $_[[0]]; # for the sake of readability.
my $title = $config{title};
my $image = $config{image};
my $help = $config{help} if($config{help});

and so on.

Dunno. The fact that so many nulls have to be passed in order to pass certain options just doesn’t seem clean to me. :slight_smile: This way at a glance you know precisely what is being passed and why, and doesn’t break old code either.