configurable variables in own file?

I

ivowel

Dear perl experts: I want to create a rather lightweight package that
just uses what is installed in standard perl. this problem must be
very common.

package mypackage:
require Exporter;
our @ISA= qw(Exporter);
our @EXPORT = qw( v1 v2 v3 v4 );
our ($v1, $v2, $v3, $v4) = ("user-please-set", "a", "b", "c");
($v1=~ /whatisit/);
## a lot more stuff, a lot more variables, etc.

so far so good. alas, I now realize that $v1 is something that I
would like my package users to change. instead of leaving it in
mypackage, I think it would be nice to have such variables layed out
into mypackageconfig.pm . mypackage should just load in
mypackageconfig.pm at compile time, and treat everything in it as its
own---like the C preprocessor #include.

optimally, I would like syntax like

package mypackage:
require Exporter;
our @ISA= qw(Exporter);
our @EXPORT = qw( v1 v2 v3 v4 );
include mypackageconfig;
our ($v2, $v3, $v4) = ("a", "b", "c");
($v1=~ /whatisit/);
## a lot more stuff, a lot more variables, etc.

and the file mypackageconfig would just contain

our $v1= "user-please-set";

is there a standard way to do this? I have been trying to accomplish
this, but always run into import/export problems.

sincerely,

/iaw
 
M

Michele Dondi

optimally, I would like syntax like

package mypackage:

Just don't use all lowercase, since these
require Exporter;
our @ISA= qw(Exporter);
our @EXPORT = qw( v1 v2 v3 v4 );
include mypackageconfig;

our ($v2, $v3, $v4) = ("a", "b", "c");
($v1=~ /whatisit/);
## a lot more stuff, a lot more variables, etc.

and the file mypackageconfig would just contain

our $v1= "user-please-set";

is there a standard way to do this? I have been trying to accomplish
this, but always run into import/export problems.

I can't see what problem could you possibly incur with require(), or
even do(). I don't see that you really need to import or export
anything, but which problems anyway?


Michele
 
B

Ben Morrow

Quoth (e-mail address removed):
Dear perl experts: I want to create a rather lightweight package that
just uses what is installed in standard perl. this problem must be
very common.

package mypackage:
require Exporter;
our @ISA= qw(Exporter);
our @EXPORT = qw( v1 v2 v3 v4 );
our ($v1, $v2, $v3, $v4) = ("user-please-set", "a", "b", "c");
($v1=~ /whatisit/);
## a lot more stuff, a lot more variables, etc.

so far so good. alas, I now realize that $v1 is something that I
would like my package users to change. instead of leaving it in
mypackage, I think it would be nice to have such variables layed out
into mypackageconfig.pm . mypackage should just load in
mypackageconfig.pm at compile time, and treat everything in it as its
own---like the C preprocessor #include.

optimally, I would like syntax like

package mypackage:

This line has a syntax error. Please copy-and-paste the *actual* code
you have run.

Also, don't use all-lowercase package names. These are reserved for
pragmas. It's probably better not to use top-level namespaces (those
without :: in) either, as the chance of conflict with some other
installed module is high. Choose some sensible top-level package for
your app, and keep everything under that. I tend to use BMORROW::* for
'private' modules I don't intend to distribute, where BMORROW is my CPAN
id.
require Exporter;
our @ISA= qw(Exporter);
our @EXPORT = qw( v1 v2 v3 v4 );
include mypackageconfig;
our ($v2, $v3, $v4) = ("a", "b", "c");
($v1=~ /whatisit/);
## a lot more stuff, a lot more variables, etc.

and the file mypackageconfig would just contain

our $v1= "user-please-set";

is there a standard way to do this? I have been trying to accomplish
this, but always run into import/export problems.

If you want to use a separate package, you can use something like

package MyPackage::Config;

require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw($v1 $v2 $v3);

our $v1 = 'foo';
our $v2 = 'bar';
our $v3 = 'baz';

__END__

package MyPackage;

use MyPackage::Config;

# now $v1 etc. have been imported into MyPackage

__END__

If you don't like all the mess at the top of MyPackage/Config.pm, you
could simply put the variables in it and load it with 'do' instead. In
that case you should not name it '.pm', as it is no longer a Perl
module.

A better (cleaner, safer) solution would be to use a proper data format.
You can use something like YAML::Tiny or Config::Tiny, and if you
*really* want to avoid any external dependencies, both those modules are
pure-Perl (they don't require a compiler to install) and have no
dependencies themselves, so you can include them directly in your own
file, like this:

package MyPackage;

use warnings;
use strict;

BEGIN {

# This persuades perl that we've actually loaded Config::Tiny
$INC{'Config/Tiny.pm'} = $0;

# copy and paste here Config/Tiny.pm, from

package Config::Tiny;

# up to

__END__

}
BEGIN { Config::Tiny->import }

Ben
 
T

Ted Zlatanov

MD> I can't see what problem could you possibly incur with require(), or
MD> even do(). I don't see that you really need to import or export
MD> anything, but which problems anyway?

Importing code just because you need data is an unnecessary security and
maintenance risk. To import data structures from an external
configuration file, the OP should use XML, YAML, a DB backend,
AppConfig, or any other mechanism specifically designed for that
purpose. I find AppConfig best for readable configurations, and YAML
best for complex data structures.

As an added benefit, with most of these there will be one place (a
logical configuration root) where configuration data can be found, so
you don't have $path and $mode and $another_config_variable all over the
code.

require() and do() should be reserved for importing Perl code.

Ted
 
T

Ted Zlatanov

On Wed, 24 Oct 2007 03:29:32 -0000 (e-mail address removed) wrote:

i> optimally, I would like syntax like

i> package mypackage:
i> require Exporter;
i> our @ISA= qw(Exporter);
i> our @EXPORT = qw( v1 v2 v3 v4 );
i> include mypackageconfig;
i> our ($v2, $v3, $v4) = ("a", "b", "c");
i> ($v1=~ /whatisit/);
i> ## a lot more stuff, a lot more variables, etc.

i> and the file mypackageconfig would just contain

i> our $v1= "user-please-set";

With AppConfig:

V1 = user-please-set
# V2 is a hash
V2 key1 = value1
V2 key2 = value2
# V3 is a list
V3 = one
V3 = two
V3 = three

YAML and XML can do this as well. YAML will handle multi-level hashes
and lists, while XML may be better depending on your environment. Any
one of them is easily parseable by other languages as well--don't limit
your data to just Perl interpretation.

The method you described has security and maintenance risks, and is not
portable.

Ted
 
M

Michele Dondi

MD> I can't see what problem could you possibly incur with require(), or
MD> even do(). I don't see that you really need to import or export
MD> anything, but which problems anyway?

Importing code just because you need data is an unnecessary security and
maintenance risk. To import data structures from an external
configuration file, the OP should use XML, YAML, a DB backend,
AppConfig, or any other mechanism specifically designed for that
purpose. I find AppConfig best for readable configurations, and YAML
best for complex data structures.

As an added benefit, with most of these there will be one place (a
logical configuration root) where configuration data can be found, so
you don't have $path and $mode and $another_config_variable all over the
code.

require() and do() should be reserved for importing Perl code.

Granted, but I was just answering his literal question.


Michele
 
T

Ted Zlatanov

MD> On Thu, 25 Oct 2007 05:29:43 -0500, Ted Zlatanov <[email protected]>
MD> wrote:

MD> I can't see what problem could you possibly incur with require(), or
MD> even do(). I don't see that you really need to import or export
MD> anything, but which problems anyway?
MD> Granted, but I was just answering his literal question.

I think it's important to see beyong the literal question. As with the
OP here, often the real need (separate configuration from code) was
hidden by the immediate need (how do I import Perl code).

Ted
 
I

ivowel

thank you everybody. I also had hidden was that I do want at least
one short sub in the configuration that an enduser should be able to
change. therefore, layout out the variables to a data file, an
obvious solution, would not work for me.

I am not particularly fond of requiring my more naive users to start
using CPAN. yes, I love CPAN for my own use, but I don't want them to
get into potential dependency issues. I want to use only modules that
come with the standard perl distribution. It is just a personal
choice, that I don't expect anyone else to share.

regards,

/ivo
 
T

Ted Zlatanov

On Thu, 25 Oct 2007 23:50:24 -0000 (e-mail address removed) wrote:

i> thank you everybody. I also had hidden was that I do want at least
i> one short sub in the configuration that an enduser should be able to
i> change.

As long as you understand that this means that the end user can make
your program do anything at all (including break it completely so it
won't run unless you take very specific precautions), this is fine.

In my experience making the end users edit code simply means they will
call you or someone like you to help them. I try to avoid that
situation by planning for the users' needs and abstracting them into
configuration options.

i> therefore, layout out the variables to a data file, an obvious
i> solution, would not work for me.

I don't know why you and many others insist on merging the notions of
configuration (pure data) and code (which includes code configuration).

Let the user write code your program will run if you wish, but at least
consider what it means to ask a user to learn Perl in order to configure
your program (for an example, consider what happens when the user tries
to use a dollar sign or a backslash, or what happens with a string like
"$var's").

i> I am not particularly fond of requiring my more naive users to start
i> using CPAN.

But you're OK asking them to write Perl code to configure your program?

i> yes, I love CPAN for my own use, but I don't want them to get into
i> potential dependency issues. I want to use only modules that come
i> with the standard perl distribution. It is just a personal choice,
i> that I don't expect anyone else to share.

Avoiding the use of CPAN is, to say the least, backwards. You can
always freeze a CPAN module with your program if you can't stand the
idea of software maintenance. Are you aware that the core 5.8, for
instance, contains modules that were not in 5.6? Does that mean you
won't use the 5.8 core modules to avoid dependency issues? Do you avoid
interactions with databases (the DBI module and related code)? How do
you justify to yourself and to your employers avoiding the use of
Regexp::Common, for example, just because you're not fond of relying on
CPAN?

Don't hide behind the "personal choice." That's nonsense. Avoiding
CPAN is a bad decision that can only be justified by a paranoid company
policy, but not by personal fondness (especially if you're paid for your
work).

Ted
 
M

Michele Dondi

thank you everybody. I also had hidden was that I do want at least
one short sub in the configuration that an enduser should be able to
change. therefore, layout out the variables to a data file, an
obvious solution, would not work for me.

I am not particularly fond of requiring my more naive users to start
using CPAN. yes, I love CPAN for my own use, but I don't want them to

Your users are naive enough to have potential problems using CPAN, yet
they are expected to be knowledgeable enough as to write a Perl sub?
Now, this sounds somewhat strange...


Michele
 
X

xhoster

Ted Zlatanov said:
On Wed, 24 Oct 2007 03:29:32 -0000 (e-mail address removed) wrote:

i> optimally, I would like syntax like

i> package mypackage:
i> require Exporter;
i> our @ISA= qw(Exporter);
i> our @EXPORT = qw( v1 v2 v3 v4 );
i> include mypackageconfig;
i> our ($v2, $v3, $v4) = ("a", "b", "c");
i> ($v1=~ /whatisit/);
i> ## a lot more stuff, a lot more variables, etc.

i> and the file mypackageconfig would just contain

i> our $v1= "user-please-set";

With AppConfig:

V1 = user-please-set
# V2 is a hash
V2 key1 = value1
V2 key2 = value2

I already know what a hash looks like in Perl. Why spend the
effort to learn what a hash looks like in some other language, too,
without some compelling reason?
# V3 is a list
V3 = one
V3 = two
V3 = three

YAML and XML can do this as well. YAML will handle multi-level hashes
and lists, while XML may be better depending on your environment. Any
one of them is easily parseable by other languages as well--don't limit
your data to just Perl interpretation.

That is a good idea if you have some inkling that your configuration file
will need to be read by some other language. But how frequent is that?
If the configuration is for my Perl program, why would anything other
than Perl and the person doing the configuration need to be able to read
it?
The method you described has security and maintenance risks,

The security risk seems to be largely a red herring to me. If the
potentially malicious user is going to be running the perl program as
himself, then he can already make the program do anything he wants just by
changing the main code itself, with no need to trick it by changing the
configuration file. If the potentially malicious user is going to be
running the code as me, well, 99% of the time I'm no more going to make the
configuration file writable by him than I am going to make the main code
itself writable by him, regardless of what mechanism is used to hold the
configuration.

And I'm not sure what you mean be maintenance risk. Any program that
actually needs a configuration in the first place is not going to run
correctly if that configuration is done wrong. This is true regardless of
what mechanism is used for holding the configuration.

There are good reasons for using text-only configuration, but those reasons
are not universally applicable, and in my experience in Perl they are not
even very common.

Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
T

Ted Zlatanov

On 26 Oct 2007 18:27:03 GMT (e-mail address removed) wrote:

x> I already know what a hash looks like in Perl. Why spend the
x> effort to learn what a hash looks like in some other language, too,
x> without some compelling reason?

You're joking, I hope. We write software for the users, not for
ourselves (I'm obviously not discussing one-off applications here). Why
should they have to learn Perl to configure things? To make sure it's
harder to port the application to another language, or to test their
intelligence in a needless chore?

AppConfig's syntax in particular is dictated by the fact that every
configuration option is available both from a file AND from the command
line, so you can say "-option1 key1=val1 -option1 key2=val2" for a hash
"option1" easily. Users seem to like that, in my experience.


x> That is a good idea if you have some inkling that your configuration file
x> will need to be read by some other language. But how frequent is that?

Again, you're joking I hope. I recommend 'The Art of Unix Programming'
for starters at http://catb.org/~esr/writings/taoup/ as I really don't
have the time to explain it all, and ESR has done a better job anyhow.

If you want to find points to argue, go for
http://catb.org/~esr/writings/taoup/html/textualitychapter.html
(Textuality) but I hope you'll read the whole book first.

x> If the configuration is for my Perl program, why would anything other
x> than Perl and the person doing the configuration need to be able to read
x> it?

(I'll use "configuration editor user" to mean the person who is supposed
to edit the configuration and has access to write it)

You're assuming a lot of things in that one sentence:

1) the configuration and the program will be forever joined
2) only your Perl application and the configuration editor user need to read it
3) only the configuration editor user is interested in its contents
4) your application will remain a Perl program forever

When they are all true, go for an all-Perl configuration. I can't see
the future so I prefer to program without those assumptions.

x> The security risk seems to be largely a red herring to me. If the
x> potentially malicious user is going to be running the perl program as
x> himself, then he can already make the program do anything he wants just by
x> changing the main code itself, with no need to trick it by changing the
x> configuration file.

You're assuming that the user running the program is the configuration
editor user. There's a risk a malicious configuration editor user will
compromise other users by editing the configuration. Even if you think
the risk is small, why take it?

Also, don't discount inadvertent security compromises where the
configuration editor user accidentally enters malicious code, and covert
compromises where the configuration editor user is tricked into entering
malicious code that looks OK at a glance.

x> If the potentially malicious user is going to be running the code as
x> me, well, 99% of the time I'm no more going to make the configuration
x> file writable by him than I am going to make the main code itself
x> writable by him, regardless of what mechanism is used to hold the
x> configuration.

I hope you see that this is a consequence of writing your configuration
as code. If the configuration can't be used to compromise the program
because it's just data, the risk is much lower and malicious users could
change options only in ways allowed by the configuration syntax.
There's still a risk from "evil" data, sure, but it's a well understood
one and Perl even has a taint mechanism to deal with it. How do you
untaint Perl code?

Let's put it another way. Do you give your programs a -e switch
analogous to Perl's, which will just run whatever is passed?

x> There are good reasons for using text-only configuration, but those reasons
x> are not universally applicable, and in my experience in Perl they are not
x> even very common.

There's too much ambiguity in your statement, sorry.

Ted
 
M

Michele Dondi

On 26 Oct 2007 18:27:03 GMT (e-mail address removed) wrote:

x> I already know what a hash looks like in Perl. Why spend the
x> effort to learn what a hash looks like in some other language, too,
x> without some compelling reason?

You're joking, I hope. We write software for the users, not for

No he's not! I think that your POVs are *complementary* rather than
conflicting, and describing two possible situations which may be
considered extremes such that one approach is well suited for one of
them and not that well suited for the other, and vice versa. Between
these two extremes there may be a continuous spectrum of situations in
which things are not that clear. But to dismiss his well reasoned
arguments a "jokes" is not fair.


Michele
 
T

Ted Zlatanov

x> I already know what a hash looks like in Perl. Why spend the
x> effort to learn what a hash looks like in some other language, too,
x> without some compelling reason?
MD> No he's not! I think that your POVs are *complementary* rather than
MD> conflicting, and describing two possible situations which may be
MD> considered extremes such that one approach is well suited for one of
MD> them and not that well suited for the other, and vice versa. Between
MD> these two extremes there may be a continuous spectrum of situations in
MD> which things are not that clear. But to dismiss his well reasoned
MD> arguments a "jokes" is not fair.

I was objecting to the use of a Perl programmer as the standard for what
a configuration editor user should know. To me, asking users to learn
Perl in order to edit a configuration file is completely unreasonable
and quite funny based on my experience. Try proposing that to the
users:

"You will configure everything in Perl."

"Is there a GUI to do this?"

"Well no, you should just learn Perl."

"OK, we'll try it. Why are some things in single and others in double
quotes?"

"That's OK, the double quotes do variable interpolation but otherwise
they are the same. You need a backslash inside double quotes for some
things, so it's best to avoid them unless blah blah blah..." (the user
has drifted off at this point)

"Grr. OK, I want to make this message multiple lines."

"Just use a here-doc. Oh, to disable interpolation you have to quote
the end-of-document marker. Or you could put it in a separate file and
write this input loop..."

"Are you serious?" (this sentence probably comes sooner in the dialog)

Ted
 
M

Michele Dondi

I was objecting to the use of a Perl programmer as the standard for what
a configuration editor user should know. To me, asking users to learn
Perl in order to edit a configuration file is completely unreasonable

I agree.
and quite funny based on my experience. Try proposing that to the

That is not what was being proposed. I think both the OP and x had in
mind a situation in which users have some Perl experience a priori.


Michele
 
T

Ted Zlatanov

MD> That is not what was being proposed. I think both the OP and x had in
MD> mind a situation in which users have some Perl experience a priori.

The OP never mentioned Perl experience about his users; he wanted a
module to avoid CPAN and to include some configuration data plus code.
His users were supposed to *edit* but not necessarily *know* Perl. In
fact you were as surprised as me that he expected them to edit Perl when
they couldn't handle CPAN installs.

xhoster used himself as the measuring stick several times, but I did not
see an implication that his users would know Perl. I think assuming the
users will know (or care to learn) Perl, if that's what xhoster and the
OP did, is a fundamental problem with an all-Perl configuration system.
If you make that assumption it's easy to justify such a system.

Ted
 
M

Michele Dondi

MD> That is not what was being proposed. I think both the OP and x had in
MD> mind a situation in which users have some Perl experience a priori.

The OP never mentioned Perl experience about his users; he wanted a
module to avoid CPAN and to include some configuration data plus code. ^^^^
^^^^

His users were supposed to *edit* but not necessarily *know* Perl. In

Well, if they are supposed to edit more or less generic code (IIRC he
talked about some subs) as opposed to simple data which can be
considered a very restricted subset of the language, the it's
difficult to suppose they have *no* experience at all. (However he did
not mention code in the very first post...)
fact you were as surprised as me that he expected them to edit Perl when
they couldn't handle CPAN installs.

I was, and I am! :)
xhoster used himself as the measuring stick several times, but I did not
see an implication that his users would know Perl. I think assuming the
users will know (or care to learn) Perl, if that's what xhoster and the
OP did, is a fundamental problem with an all-Perl configuration system.
If you make that assumption it's easy to justify such a system.

Anyway it's largely a problem of OP's and I think it is moot to lose
time continuing to argue each other when basically we all agree, after
all!


Michele
 
I

ivowel

I did not write the constitution, so wondering about OP intent seems
funny. :) Thanks everyone.

As pointed out, I do not worry about an end user injecting code.
Users of my program download it and have full access to it. If they
want to inject, let them.

Yes, I may be schizophrenic in assuming some ability of my users to
read and change my perl. By laying configuration out to a
'makechangeshere.pm' file, I hope this is a little easier than reading
my entire program. As to CPAN, I just don't want to worry about users
ending up having to do deep installs with many dependencies. They may
also not have root access. My view may be wrong. Maybe I should just
go this route.

As to my code, I am thinking that a user may have to change one sub:

sub http2file {
my $httpname= $_[0]; # the http://www.domain.com/file.html
(defined($httpname)) or htmldie("You cannot call http2file without
an http name.\n");
($httpname =~ /^http:\/\//) or htmldie("You cannot call http2file
with '$httpname'.\n");
$httpname=~ s/^http:\/\///; # eliminate the http
$httpname =~ /([^\/]+)\/(.*)/; # separate the domain name
and the filename
my $hostname= $1;
my $fname= $2 || "index.html"; # default; could be made
smarter
my $filename = "/var/www/$hostname/htdocs/$fname"; # rewrite the
filename
$filename=~ s/\?.*//; # kill everything after the
'?'
return $filename;
}

For standard cases, this should work fine. (Probably some bugs in the
code, too, but as I said, for standard cases, it should work.) It's
the only routine that my user needs to change---and yes, it may be
painful. The rest of the configuration are just variables, that I
could have laid out into a configuration file.

(My application is a lightweight wiki that can be easily bolted onto
existing web pages, is less than 300 lines of real code, and requires
very little for its installation. In case anyone is interested,
http://welch.econ.brown.edu/computers/MiniWiki.tgz . There are
probably better alternatives elsewhere, though. I am not a pro,
programming is just a hobby.)

Thanks again, everyone.

/iaw
 
T

Tad McClellan

As to CPAN, I just don't want to worry about users
ending up having to do deep installs with many dependencies. They may
also not have root access.


You do not need root access to install Perl modules.

As to my code, I am thinking that a user may have to change one sub:

sub http2file {
my $httpname= $_[0]; # the http://www.domain.com/file.html
(defined($httpname)) or htmldie("You cannot call http2file without
an http name.\n");


Your message should tell them what to do rather than telling them
what they just did.


defined $httpname or htmldie("http2file must be called with an argument");

($httpname =~ /^http:\/\//) or htmldie("You cannot call http2file
with '$httpname'.\n");
$httpname=~ s/^http:\/\///; # eliminate the http


There is no need to match before substituting:

unless ( $httpname=~ s#^http://## ) {
htmldie("the argument to http2file() must start with 'http://'\n");
}

$httpname =~ /([^\/]+)\/(.*)/; # separate the domain name
and the filename
my $hostname= $1;


You should never use the dollar-digit variables unless you have
first tested that the match *succeeded*.

my $fname= $2 || "index.html"; # default; could be made
smarter


my($hostname, $fname) = split m#/#, $httpname, 2;

($fname does not necessarily contain a filename you know...)

For standard cases, this should work fine.


Is $httpname = 'foo.com/bar/index.html' a "standard case"?

I am not a pro,
programming is just a hobby.)


A disclaimer is not necessary here, we can tell. :)
 
T

Ted Zlatanov

On Wed, 31 Oct 2007 01:32:57 -0000 (e-mail address removed) wrote:

i> As to CPAN, I just don't want to worry about users ending up having
i> to do deep installs with many dependencies. They may also not have
i> root access. My view may be wrong. Maybe I should just go this
i> route.

I really doubt you'll find disagreement on this one thing: use CPAN as
much as possible. It makes everyone's life easier: you, your users, and
ours.

i> sub http2file {
i> my $httpname= $_[0]; # the http://www.domain.com/file.html
i> (defined($httpname)) or htmldie("You cannot call http2file without
i> an http name.\n");
i> ($httpname =~ /^http:\/\//) or htmldie("You cannot call http2file
i> with '$httpname'.\n");
i> $httpname=~ s/^http:\/\///; # eliminate the http
i> $httpname =~ /([^\/]+)\/(.*)/; # separate the domain name
i> and the filename
i> my $hostname= $1;
i> my $fname= $2 || "index.html"; # default; could be made
i> smarter
i> my $filename = "/var/www/$hostname/htdocs/$fname"; # rewrite the
i> filename
i> $filename=~ s/\?.*//; # kill everything after the
i> '?'
i> return $filename;
i> }

i> For standard cases, this should work fine. (Probably some bugs in the
i> code, too, but as I said, for standard cases, it should work.) It's
i> the only routine that my user needs to change---and yes, it may be
i> painful. The rest of the configuration are just variables, that I
i> could have laid out into a configuration file.

OK, so you want a mapping from a URL path to file. A simple way to do
this as a configuration setting is:

# use any format you like to set this
FILE_ROOT = /var/www/HOSTNAME/htdocs

Then the user can simply change this as needed, setting that directory.
Do you see how much simpler the above is for the users? Your http2file
function is then (untested code):

use URI;

my $url = shift @_;
my $from = URI->new($url, 'http');
my $to = $config->{FILE_ROOT};

my $path = $from->path();

if ($path eq '' || $path eq '/')
{
$path = '/index.html';
}

$file = sprintf('%s/%s', $to, $path);

# validate $file now
htmldie "$file was not readable or not a file" unless (-r $file && -f $file);

return $file;

I'd use the CPAN URI module to parse the URL and extract the path (the
only piece you need). It really makes the job easier. At least look at
the docs to see what it can do, and what the expected URL formats are.
It will catch query parameters and fragments, along with much more.

You can also add validation to make sure the host name is something
expected, but if you're aiming for simplicity the above may be the best
solution for you.

Try the code below if you're not sure about what the URI module does:

foreach my $url ('/path.html',
'http://lifelogs.com',
'http://lifelogs.com/',
'http://lifelogs.com/test.html',
'http://lifelogs.com/test.html?extraparameters=yes',
'http://lifelogs.com/test.html?extraparameters=yes#fragment')
{
my $from = URI->new($url, 'http');
my $query = $from->query() || '';
printf "[$url]:\n\thost is [%s], port is [%s], path is [%s], query is [%s]\n", $from->host(), $from->port(), $from->path(), $query;
}

Note carefully how many things it does correctly, especially the first
one, which will give you an undefined host name but a good path.

Ted
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top