Gossamer Forum
Home : General : Perl Programming :

Got me stumped.....

(Page 1 of 2)
> >
Quote Reply
Got me stumped.....
Hi,

I am making a mailing list script to beat all others :)

Can someone please tell me why this code tells you that you are not subscribed to the mailing list no matter what you enter?

The format of email.db is email|name so like paul@perlmad.com|Paul Wilson

Code:
sub unsubscribe {

check();

open(DB,"<$email_db_path$email_db") || die &error("The email database could not be accessed : $!");
@addresses=<DB>;
close(DB);

foreach $line (@addresses) {
chomp $line;
($e,$n) = split(/\|/,$line);
if ($e ne $email) {
&error("You are not subscribed to this mailing list, therefore you cannot unsubscribe.");
}
}

print "Location: $redirect_unsub\n\n";
}
I currently have this in email.db

perlmad@perlmad.com|Paul Wilson

...but when I enter the exact information into the unsubscribe form, it gives the error.


Thankyou :)


Paul Wilson.
Installations:
http://www.wiredon.net/gt/
Quote Reply
Re: Got me stumped..... In reply to
I don't see how you have defined $email???

You would need to define it like:

Code:

my $email = $in{'email'};


Or if you intend on using CGI.pm, which I would recommend, then you would use:

Code:

my $email = $in->param('email');


Regards,

Eliot Lee
Quote Reply
Re: Got me stumped..... In reply to
Hi sorry I forgot to mention, at the top of the script I have

$name = $cfg->param('name');
$email = $cfg->param('email');


I am using

use CGI qw(:standard);

....and have

$cfg = new CGI;

Paul Wilson.
Installations:
http://www.wiredon.net/gt/
Quote Reply
Re: Got me stumped..... In reply to
After you assign the variables from their param, print them to make sure they're getting what you expect.

Other then that, I don't see anything in the code you posted showing why it wouldntt match. In fact, I just traced through in an ide, and it was fine. Something on the input is wrong.

can yo provide a link to a .txt of the whole script?



Quote Reply
Re: Got me stumped..... In reply to
Yeah no probs as long as people don't steal it or take the mick out of my regex Smile

http://----------

Paul Wilson.
Installations:
http://www.wiredon.net/gt/
Quote Reply
  In reply to
Argh, I uploaded an old copy by accident - the new one is uploaded now.
Quote Reply
Re: In reply to
I stepped through it in an ide. It worked just fine. Again, I'd say check on your input.

--mark

Quote Reply
Re: Got me stumped..... In reply to
if ($e ne $email) {

just a thought.. but shouldn't that be..

if ($e eq $email) {

:P

Jerry Su
widgetz sucks
Quote Reply
Re: Got me stumped..... In reply to
Ah, that's it.... it's going thru that loop for each name in the list that doesn't match, so if the first name in the list isnt the inputted one, it calls the error routine and exits when done. good eye. i was testing it with the one entry so it worked fine LOL

Quote Reply
Re: Got me stumped..... In reply to
Hi,

Thanks for your time but I don't think that is right because Im checking that the inputted email doesn't match the emails in the database, and then show the error. The error says "You aren't subscribed so you can't unsubscribe", and so if I use eq and they input paul@domain.com but that email isn't in the database, then the error won't show when it needs to. Did that make sense?

Example...

In the database I have.....

paul@paul.com|Paul Wilson
perl@paul.com|Paul Wilson

On the unsubscribe form they enter paul@paul.com, therefore that is an existing email address and so can be unsubscribed, but by using Jerry's method it is saying if the input matches an email in the database then show the error, which is "You aren't subscribed, so you can't unsubscribe", so that would be the wrong error because they are infact subscribed. So by using ne like I was originally then that is saying if the input doesn't equal any email address in the database then tell them they aren't subscribed, which is the correct error.

Am I barking up the wrong tree?

Thanks.


Paul Wilson.
Installations:
http://www.wiredon.net/gt/
Quote Reply
Re: Got me stumped..... In reply to
Say your file looks like this:

mbadolato@cybernox.com|Mark Badolato
someone@somewhere.com|Joe Someone
perlmad@perlmad.com|Paul Wilson

You tell it to delete perlmad@perlmad.com

$email is 'perlmad@perlmad.com'
It reads in the file. Starts to check.

foreach ($line)....
on element 1:'mbadolato@cybernox.com|Mark Badolato'
splits:
$e = 'mbadolato@cybernox.com'
$n = 'Mark Badolato'

compares:
if ($email ne $e)
(or.... if 'perlmad@perlmad.com' ne 'mbadolato@cybernox.com')

Nope they don't match. Call the error() routine.

Prints they aren't matched

exits

It never makes it to the other elements in the array due to the exit.

You need to change your logic around. Loop though the array and when you find a match, remove it, otherwise just keep looping. If a match never gets found, then call the error() routine.

--mark

Quote Reply
Re: Got me stumped..... In reply to
Ok I understand what you mean now - so would this be more appropriate?

Code:
check();

open(DB,"<$email_db_path$email_db") || die &error("The email database could not be accessed : $!");
@addresses=<DB>;
close(DB);

foreach $line (@addresses) {
chomp $line;
($e,$n) = split(/\|/,$line);
if ($e eq $email) {
REMOVE IT
} else {
No match - ERROR()
}
}
Is that more along the right track?

Thankyou for help...and Jerry too....

Paul Wilson.
Installations:
http://www.wiredon.net/gt/
Quote Reply
Re: Got me stumped..... In reply to
Hi Paul:

That'll work if the email address searched on is the first one in the file (array) Wink Instead you could flag if found, and use the flag outside the loop to handle if found or not. Have you considered using grep instead? Quicker and less code.


Dan Cool

LotusLand
Vancouver, BC, Canada
Top Ranked City in World for Quality of Life
Quote Reply
Re: Got me stumped..... In reply to
In Reply To:
That'll work if the email address searched on is the first one in the file
Hi, but it is in a foreach loop - it checks the whole file....doesn't it?

@emails=<DB>;

That put the whole of the file into @emails and then the foreach loop checks the input again each line - that what I thought anyway.

I would appreciate an example of the grep method.

Is it something like....

grep(/$email/, @addresses);

Thanks.

Paul Wilson.
Installations:
http://www.wiredon.net/gt/
Quote Reply
Re: Got me stumped..... In reply to
Hi Paul:

if (! grep (/^$email/, @addresses)) {
No match - ERROR()
}


Dan Cool

LotusLand
Vancouver, BC, Canada
Top Ranked City in World for Quality of Life
Quote Reply
Re: Got me stumped..... In reply to
The foreach would loop thru the entire file, but your error routine contains an exit, thus terminating the program


Quote Reply
Re: Got me stumped..... In reply to
Thanks guys Smile

Paul Wilson.
Installations:
http://www.wiredon.net/gt/
Quote Reply
Re: Got me stumped..... In reply to
Ewww now I don't get an error at all even if I enter a non-existant email.

This is what I have.....

Code:
open(DB,"<$email_db_path$email_db") || die &error("The email database could not be accessed : $!");
@addresses=<DB>;
close(DB);

if (! grep (/^$email/, @addresses)) {
&error("You are not subscribed to the mailing list, you therefore cannot unsubscribe.");
}
Paul Wilson.
Installations:
http://www.wiredon.net/gt/
Quote Reply
Re: Got me stumped..... In reply to
I just thought of a different approach but didn't wanted to change your whole sub/unsub system.

So here's a combo:

Code:
sub unsubscribe {

check();

open(DB,"<$email_db_path$email_db") || die &error("The email database could not be accessed : $!");
@addresses=<DB>;
close(DB);

$valid = 0;
foreach $line (@addresses) {
chomp $line;
($e,$n) = split(/\|/,$line);
if ($e eq $email) {
$valid = 1;
}
}

$valid or &error ("You are not subscribed to this mailing list, therefore you cannot unsubscribe.");
# Made it this far, so now you can start removing the user.

$data = "$e|$n";
$line =~ s/$data//;
push(@addresses,$line);

open(DB,">$email_db_path$email_db") || die &error("The email database could not be accessed : $!");
foreach (@addresses) {
print DB "$_\n";
}
close(DB);
print "Location: $redirect_unsub\n\n";

}
...maybe i'm totally wrong Wink

Quote Reply
Re: Got me stumped..... In reply to
Thanks, I'll give it a try at least......

Paul Wilson.
Installations:
http://www.wiredon.net/gt/
Quote Reply
Re: Got me stumped..... In reply to
This block of code doens't make sense... and I don't see how it would work.
Code:
$data = "$e|$n";
$line =~ s/$data//;
push(@addresses,$line);
$e and $n will be the last set of values in the foreach loop because you don't have last here:
Code:
if ($e eq $email) {
$valid = 1;
}
This:
Code:
$data = "$e|$n";
$line =~ s/$data//;
Is the same thing as:
Code:
$line = '';
Then you add a null value to the end of an array?
Code:
push(@addresses,$line);
I was thinking something along the lines of:
Code:
@newdata = grep { !/$line/e } @addresses;
open(DB,">$email_db_path$email_db") || die &error("The email database could not be accessed : $!");
map { print DB "$_\n" } @newdata;
close(DB);
Similar to Dan's original suggestion.

--Drew
Quote Reply
Re: Got me stumped..... In reply to
Excellent, thanks Junko - I was trying to work out how to unsubscribe the user but was having trouble removing the relevant line so that code was a temporary experiment....

$data = "$e|$n";
$line =~ s/$data//;
push(@addresses,$line);

I was trying to replace $e|$n with nothing, hence s/$data//;, and then add the empty line to the end and re-print the data to the file and get rid of the blank line at the end.

I'm not familiar with grep and map so that's why I didn't attempt to use them

Thanks for the tip..

I assume I still need something before that code to remove the email and name of the person unsubscribing, and your code re-writes the new data to the database?


Installations:http://www.wiredon.net/gt/
Support: http://www.wiredon.net/forum/

Quote Reply
Re: Got me stumped..... In reply to
Try this Crazy
Code:
sub unsubscribe {
check();
open(DB, "<$email_db_path$email_db") || die ("The email database could not be accessed : $!");
@old = <DB>; #suck the database into an array
close (DB);
@new = grep { !/^$email/ } @old; #remove the record if it exists
if ($#new != $#data) { #was a record removed?
open(DB, ">$email_db_path$email_db") || die &error("The email database could not be accessed : $!");
flock (DB, 2);
map { print DB "$_" } @new; #rewrite the data
close(DB);
} else { #otherwise have a fit :-)
error("could not unsubscribe\n");
}
print "Location: $redirect_unsub\n\n";
}
You could also do a while loop and junk and read/write at the same time if you wanted to cut down on code.

Grep and map are kind of like foreach loops...

Code:
@new = grep { /^foo/ } @old;
is the same thing as:
Code:
foreach (@old) {
if (/^foo/) {
push @new;
}
}
and
Code:
map { print } @array;
is the same thing as:
Code:
foreach (@array) {
print;
}
--Drew
Quote Reply
Re: Got me stumped..... In reply to
Thanks Junko I'll let you know how I get on.

Thanks for explaining a bit about map and grep also......


Paul
Installations:http://wiredon.net/gt/
Support: http://wiredon.net/forum/

Quote Reply
Re: Got me stumped..... In reply to
Junko, just one more question.....

I don't get this line.....

if ($#new != $#data) {

What is $#data?

Paul
Installations:http://wiredon.net/gt/
Support: http://wiredon.net/forum/

> >