X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=pod%2Fperlfaq9.pod;h=609f8984851bdb5c16f88091d9687ce846b83593;hb=b9ad30b40cf004f5ea6fd7a945a950cf873aed7b;hp=1a5e61feee85cd1417931dae926c8964ed9b2b19;hpb=1fa0e54f2e0b168f2a77a752f92064a58da05ee4;p=p5sagit%2Fp5-mst-13.2.git diff --git a/pod/perlfaq9.pod b/pod/perlfaq9.pod index 1a5e61f..609f898 100644 --- a/pod/perlfaq9.pod +++ b/pod/perlfaq9.pod @@ -1,45 +1,70 @@ =head1 NAME -perlfaq9 - Networking ($Revision: 1.20 $, $Date: 1998/06/22 18:31:09 $) +perlfaq9 - Networking ($Revision: 8539 $) =head1 DESCRIPTION This section deals with questions related to networking, the internet, and a few on the web. -=head2 My CGI script runs from the command line but not the browser. (500 Server Error) +=head2 What is the correct form of response from a CGI script? -If you can demonstrate that you've read the following FAQs and that -your problem isn't something simple that can be easily answered, you'll -probably receive a courteous and useful reply to your question if you -post it on comp.infosystems.www.authoring.cgi (if it's something to do -with HTTP, HTML, or the CGI protocols). Questions that appear to be Perl -questions but are really CGI ones that are posted to comp.lang.perl.misc -may not be so well received. +(Alan Flavell answers...) + +The Common Gateway Interface (CGI) specifies a software interface between +a program ("CGI script") and a web server (HTTPD). It is not specific +to Perl, and has its own FAQs and tutorials, and usenet group, +comp.infosystems.www.authoring.cgi + +The CGI specification is outlined in an informational RFC: +http://www.ietf.org/rfc/rfc3875 + +Other relevant documentation listed in: http://www.perl.org/CGI_MetaFAQ.html + +These Perl FAQs very selectively cover some CGI issues. However, Perl +programmers are strongly advised to use the CGI.pm module, to take care +of the details for them. + +The similarity between CGI response headers (defined in the CGI +specification) and HTTP response headers (defined in the HTTP +specification, RFC2616) is intentional, but can sometimes be confusing. + +The CGI specification defines two kinds of script: the "Parsed Header" +script, and the "Non Parsed Header" (NPH) script. Check your server +documentation to see what it supports. "Parsed Header" scripts are +simpler in various respects. The CGI specification allows any of the +usual newline representations in the CGI response (it's the server's +job to create an accurate HTTP response based on it). So "\n" written in +text mode is technically correct, and recommended. NPH scripts are more +tricky: they must put out a complete and accurate set of HTTP +transaction response headers; the HTTP specification calls for records +to be terminated with carriage-return and line-feed, i.e ASCII \015\012 +written in binary mode. -The useful FAQs and related documents are: +Using CGI.pm gives excellent platform independence, including EBCDIC +systems. CGI.pm selects an appropriate newline representation +($CGI::CRLF) and sets binmode as appropriate. - CGI FAQ - http://www.webthing.com/page.cgi/cgifaq +=head2 My CGI script runs from the command line but not the browser. (500 Server Error) - Web FAQ - http://www.boutell.com/faq/ +Several things could be wrong. You can go through the "Troubleshooting +Perl CGI scripts" guide at - WWW Security FAQ - http://www.w3.org/Security/Faq/ + http://www.perl.org/troubleshooting_CGI.html - HTTP Spec - http://www.w3.org/pub/WWW/Protocols/HTTP/ +If, after that, you can demonstrate that you've read the FAQs and that +your problem isn't something simple that can be easily answered, you'll +probably receive a courteous and useful reply to your question if you +post it on comp.infosystems.www.authoring.cgi (if it's something to do +with HTTP or the CGI protocols). Questions that appear to be Perl +questions but are really CGI ones that are posted to comp.lang.perl.misc +are not so well received. - HTML Spec - http://www.w3.org/TR/REC-html40/ - http://www.w3.org/pub/WWW/MarkUp/ +The useful FAQs, related documents, and troubleshooting guides are +listed in the CGI Meta FAQ: - CGI Spec - http://www.w3.org/CGI/ + http://www.perl.org/CGI_MetaFAQ.html - CGI Security FAQ - http://www.go2net.com/people/paulp/cgi-security/safe-cgi.txt =head2 How can I get better error messages from a CGI program? @@ -76,15 +101,16 @@ stamp prepended. =head2 How do I remove HTML from a string? -The most correct way (albeit not the fastest) is to use HTML::Parse -from CPAN (part of the libwww-perl distribution, which is a must-have -module for all web hackers). +The most correct way (albeit not the fastest) is to use HTML::Parser +from CPAN. Another mostly correct +way is to use HTML::FormatText which not only removes HTML but also +attempts to do a little simple formatting of the resulting plain text. Many folks attempt a simple-minded regular expression approach, like -C.*?E//g>, but that fails in many cases because the tags +C<< s/<.*?>//g >>, but that fails in many cases because the tags may continue over line breaks, they may contain quoted angle-brackets, -or HTML comment may be present. Plus folks forget to convert -entities, like C<<> for example. +or HTML comment may be present. Plus, folks forget to convert +entities--like C<<> for example. Here's one "simple-minded" approach, that works for most files: @@ -93,7 +119,7 @@ Here's one "simple-minded" approach, that works for most files: If you want a more complete solution, see the 3-stage striphtml program in -http://www.perl.com/CPAN/authors/Tom_Christiansen/scripts/striphtml.gz +http://www.cpan.org/authors/Tom_Christiansen/scripts/striphtml.gz . Here are some tricky cases that you should think about when picking @@ -101,7 +127,7 @@ a solution: A > B - A > B @@ -121,36 +147,68 @@ on text like this: =head2 How do I extract URLs? -A quick but imperfect approach is +You can easily extract all sorts of URLs from HTML with +C which handles anchors, images, objects, +frames, and many other tags that can contain a URL. If you need +anything more complex, you can create your own subclass of +C or C. You might even use +C as an example for something specifically +suited to your needs. + +You can use URI::Find to extract URLs from an arbitrary text document. + +Less complete solutions involving regular expressions can save +you a lot of processing time if you know that the input is simple. One +solution from Tom Christiansen runs 100 times faster than most +module based approaches but only extracts URLs from anchors where the first +attribute is HREF and there are no other attributes. + + #!/usr/bin/perl -n00 + # qxurl - tchrist@perl.com + print "$2\n" while m{ + < \s* + A \s+ HREF \s* = \s* (["']) (.*?) \1 + \s* > + }gsix; - #!/usr/bin/perl -n00 - # qxurl - tchrist@perl.com - print "$2\n" while m{ - < \s* - A \s+ HREF \s* = \s* (["']) (.*?) \1 - \s* > - }gsix; - -This version does not adjust relative URLs, understand alternate -bases, deal with HTML comments, deal with HREF and NAME attributes in -the same tag, or accept URLs themselves as arguments. It also runs -about 100x faster than a more "complete" solution using the LWP suite -of modules, such as the -http://www.perl.com/CPAN/authors/Tom_Christiansen/scripts/xurl.gz -program. =head2 How do I download a file from the user's machine? How do I open a file on another machine? -In the context of an HTML form, you can use what's known as -B encoding. The CGI.pm module (available from -CPAN) supports this in the start_multipart_form() method, which isn't -the same as the startform() method. +In this case, download means to use the file upload feature of HTML +forms. You allow the web surfer to specify a file to send to your web +server. To you it looks like a download, and to the user it looks +like an upload. No matter what you call it, you do it with what's +known as B encoding. The CGI.pm module (which +comes with Perl as part of the Standard Library) supports this in the +start_multipart_form() method, which isn't the same as the startform() +method. + +See the section in the CGI.pm documentation on file uploads for code +examples and details. + +=head2 How do I make an HTML pop-up menu with Perl? -=head2 How do I make a pop-up menu in HTML? +(contributed by brian d foy) + +The CGI.pm module (which comes with Perl) has functions to create +the HTML form widgets. See the CGI.pm documentation for more +examples. + + use CGI qw/:standard/; + print header, + start_html('Favorite Animals'), + + start_form, + "What's your favorite animal? ", + popup_menu( + -name => 'animal', + -values => [ qw( Llama Alpaca Camel Ram ) ] + ), + submit, + + end_form, + end_html; -Use the BSELECTE> and BOPTIONE> tags. The CGI.pm -module (available from CPAN) supports this widget, as well as many -others, including some that it cleverly synthesizes on its own. =head2 How do I fetch an HTML file? @@ -160,8 +218,9 @@ on your system, is this: $html_code = `lynx -source $url`; $text_data = `lynx -dump $url`; -The libwww-perl (LWP) modules from CPAN provide a more powerful way to -do this. They work through proxies, and don't require lynx: +The libwww-perl (LWP) modules from CPAN provide a more powerful way +to do this. They don't require lynx, but like lynx, can still work +through proxies: # simplest version use LWP::Simple; @@ -169,11 +228,12 @@ do this. They work through proxies, and don't require lynx: # or print HTML from a URL use LWP::Simple; - getprint "http://www.sn.no/libwww-perl/"; + getprint "http://www.linpro.no/lwp/"; # or print ASCII from HTML from a URL + # also need HTML-Tree package from CPAN use LWP::Simple; - use HTML::Parse; + use HTML::Parser; use HTML::FormatText; my ($html, $ascii); $html = get("http://www.perl.com/"); @@ -184,6 +244,10 @@ do this. They work through proxies, and don't require lynx: =head2 How do I automate an HTML form submission? +If you are doing something complex, such as moving through many pages +and forms or a web site, you can use C. See its +documentation for all the details. + If you're submitting values using the GET method, create a URL and encode the form using the C method: @@ -207,51 +271,75 @@ the content appropriately. =head2 How do I decode or create those %-encodings on the web? -Here's an example of decoding: +If you are writing a CGI script, you should be using the CGI.pm module +that comes with perl, or some other equivalent module. The CGI module +automatically decodes queries for you, and provides an escape() +function to handle encoding. - $string = "http://altavista.digital.com/cgi-bin/query?pg=q&what=news&fmt=.&q=%2Bcgi-bin+%2Bperl.exe"; - $string =~ s/%([a-fA-F0-9]{2})/chr(hex($1))/ge; +The best source of detailed information on URI encoding is RFC 2396. +Basically, the following substitutions do it: -Encoding is a bit harder, because you can't just blindly change -all the non-alphanumunder character (C<\W>) into their hex escapes. -It's important that characters with special meaning like C and C -I be translated. Probably the easiest way to get this right is -to avoid reinventing the wheel and just use the URI::Escape module, -which is part of the libwww-perl package (LWP) available from CPAN. + s/([^\w()'*~!.-])/sprintf '%%%02x', ord $1/eg; # encode + + s/%([A-Fa-f\d]{2})/chr hex $1/eg; # decode + s/%([[:xdigit:]]{2})/chr hex $1/eg; # same thing + +However, you should only apply them to individual URI components, not +the entire URI, otherwise you'll lose information and generally mess +things up. If that didn't explain it, don't worry. Just go read +section 2 of the RFC, it's probably the best explanation there is. + +RFC 2396 also contains a lot of other useful information, including a +regexp for breaking any arbitrary URI into components (Appendix B). =head2 How do I redirect to another page? -Instead of sending back a C as the headers of your -reply, send back a C header. Officially this should be a -C header, so the CGI.pm module (available from CPAN) sends back -both: +Specify the complete URL of the destination (even if it is on the same +server). This is one of the two different kinds of CGI "Location:" +responses which are defined in the CGI specification for a Parsed Headers +script. The other kind (an absolute URLpath) is resolved internally to +the server without any HTTP redirection. The CGI specifications do not +allow relative URLs in either case. + +Use of CGI.pm is strongly recommended. This example shows redirection +with a complete URL. This redirection is handled by the web browser. + + use CGI qw/:standard/; - Location: http://www.domain.com/newpage - URI: http://www.domain.com/newpage + my $url = 'http://www.cpan.org/'; + print redirect($url); -Note that relative URLs in these headers can cause strange effects -because of "optimizations" that servers do. - $url = "http://www.perl.com/CPAN/"; - print "Location: $url\n\n"; - exit; +This example shows a redirection with an absolute URLpath. This +redirection is handled by the local web server. + + my $url = '/CPAN/index.html'; + print redirect($url); + + +But if coded directly, it could be as follows (the final "\n" is +shown separately, for clarity), using either a complete URL or +an absolute URLpath. + + print "Location: $url\n"; # CGI response header + print "\n"; # end of headers -To be correct to the spec, each of those C<"\n"> -should really each be C<"\015\012">, but unless you're -stuck on MacOS, you probably won't notice. =head2 How do I put a password on my web pages? -That depends. You'll need to read the documentation for your web -server, or perhaps check some of the other FAQs referenced above. +To enable authentication for your web server, you need to configure +your web server. The configuration is different for different sorts +of web servers--apache does it differently from iPlanet which does +it differently from IIS. Check your web server documentation for +the details for your particular server. =head2 How do I edit my .htpasswd and .htgroup files with Perl? The HTTPD::UserAdmin and HTTPD::GroupAdmin modules provide a consistent OO interface to these files, regardless of how they're -stored. Databases may be text, dbm, Berkley DB or any database with a -DBI compatible driver. HTTPD::UserAdmin supports files used by the -`Basic' and `Digest' authentication schemes. Here's an example: +stored. Databases may be text, dbm, Berkeley DB or any database with +a DBI compatible driver. HTTPD::UserAdmin supports files used by the +"Basic" and "Digest" authentication schemes. Here's an example: use HTTPD::UserAdmin (); HTTPD::UserAdmin @@ -260,21 +348,14 @@ DBI compatible driver. HTTPD::UserAdmin supports files used by the =head2 How do I make sure users can't enter values into a form that cause my CGI script to do bad things? -Read the CGI security FAQ, at -http://www-genome.wi.mit.edu/WWW/faqs/www-security-faq.html, and the -Perl/CGI FAQ at -http://www.perl.com/CPAN/doc/FAQs/cgi/perl-cgi-faq.html. +See the security references listed in the CGI Meta FAQ -In brief: use tainting (see L), which makes sure that data -from outside your script (eg, CGI parameters) are never used in -C or C calls. In addition to tainting, never use the -single-argument form of system() or exec(). Instead, supply the -command and arguments as a list, which prevents shell globbing. + http://www.perl.org/CGI_MetaFAQ.html =head2 How do I parse a mail header? For a quick-and-dirty solution, try this solution derived -from page 222 of the 2nd edition of "Programming Perl": +from L: $/ = ''; $header = ; @@ -287,92 +368,110 @@ the Mail::Header module from CPAN (part of the MailTools package). =head2 How do I decode a CGI form? -You use a standard module, probably CGI.pm. Under no circumstances -should you attempt to do so by hand! - -You'll see a lot of CGI programs that blindly read from STDIN the number -of bytes equal to CONTENT_LENGTH for POSTs, or grab QUERY_STRING for -decoding GETs. These programs are very poorly written. They only work -sometimes. They typically forget to check the return value of the read() -system call, which is a cardinal sin. They don't handle HEAD requests. -They don't handle multipart forms used for file uploads. They don't deal -with GET/POST combinations where query fields are in more than one place. -They don't deal with keywords in the query string. - -In short, they're bad hacks. Resist them at all costs. Please do not be -tempted to reinvent the wheel. Instead, use the CGI.pm or CGI_Lite.pm -(available from CPAN), or if you're trapped in the module-free land -of perl1 .. perl4, you might look into cgi-lib.pl (available from -http://www.bio.cam.ac.uk/web/form.html). - -Make sure you know whether to use a GET or a POST in your form. -GETs should only be used for something that doesn't update the server. -Otherwise you can get mangled databases and repeated feedback mail -messages. The fancy word for this is ``idempotency''. This simply -means that there should be no difference between making a GET request -for a particular URL once or multiple times. This is because the -HTTP protocol definition says that a GET request may be cached by the -browser, or server, or an intervening proxy. POST requests cannot be -cached, because each request is independent and matters. Typically, -POST requests change or depend on state on the server (query or update -a database, send mail, or purchase a computer). +(contributed by brian d foy) + +Use the CGI.pm module that comes with Perl. It's quick, +it's easy, and it actually does quite a bit of work to +ensure things happen correctly. It handles GET, POST, and +HEAD requests, multipart forms, multivalued fields, query +string and message body combinations, and many other things +you probably don't want to think about. + +It doesn't get much easier: the CGI module automatically +parses the input and makes each value available through the +C function. + + use CGI qw(:standard); + + my $total = param( 'price' ) + param( 'shipping' ); + + my @items = param( 'item' ); # multiple values, same field name + +If you want an object-oriented approach, CGI.pm can do that too. + + use CGI; + + my $cgi = CGI->new(); + + my $total = $cgi->param( 'price' ) + $cgi->param( 'shipping' ); + + my @items = $cgi->param( 'item' ); + +You might also try CGI::Minimal which is a lightweight version +of the same thing. Other CGI::* modules on CPAN might work better +for you, too. + +Many people try to write their own decoder (or copy one from +another program) and then run into one of the many "gotchas" +of the task. It's much easier and less hassle to use CGI.pm. =head2 How do I check a valid mail address? -You can't, at least, not in real time. Bummer, eh? +(partly contributed by Aaron Sherman) -Without sending mail to the address and seeing whether there's a human -on the other hand to answer you, you cannot determine whether a mail -address is valid. Even if you apply the mail header standard, you -can have problems, because there are deliverable addresses that aren't -RFC-822 (the mail header standard) compliant, and addresses that aren't -deliverable which are compliant. - -Many are tempted to try to eliminate many frequently-invalid -mail addresses with a simple regexp, such as -C. It's a very bad idea. However, -this also throws out many valid ones, and says nothing about -potential deliverability, so is not suggested. Instead, see -http://www.perl.com/CPAN/authors/Tom_Christiansen/scripts/ckaddr.gz , -which actually checks against the full RFC spec (except for nested -comments), looks for addresses you may not wish to accept mail to -(say, Bill Clinton or your postmaster), and then makes sure that the -hostname given can be looked up in the DNS MX records. It's not fast, -but it works for what it tries to do. +This isn't as simple a question as it sounds. There are two parts: -Our best advice for verifying a person's mail address is to have them -enter their address twice, just as you normally do to change a password. -This usually weeds out typos. If both versions match, send -mail to that address with a personal message that looks somewhat like: +a) How do I verify that an email address is correctly formatted? - Dear someuser@host.com, +b) How do I verify that an email address targets a valid recipient? - Please confirm the mail address you gave us Wed May 6 09:38:41 - MDT 1998 by replying to this message. Include the string - "Rumpelstiltskin" in that reply, but spelled in reverse; that is, - start with "Nik...". Once this is done, your confirmed address will - be entered into our records. +Without sending mail to the address and seeing whether there's a human +on the other end to answer you, you cannot fully answer part I, but +either the C or the C module will do +both part I and part I as far as you can in real-time. + +If you want to just check part I to see that the address is valid +according to the mail header standard with a simple regular expression, +you can have problems, because there are deliverable addresses that +aren't RFC-2822 (the latest mail header standard) compliant, and +addresses that aren't deliverable which, are compliant. However, the +following will match valid RFC-2822 addresses that do not have comments, +folding whitespace, or any other obsolete or non-essential elements. +This I matches the address itself: + + my $atom = qr{[a-zA-Z0-9_!#\$\%&'*+/=?\^`{}~|\-]+}; + my $dot_atom = qr{$atom(?:\.$atom)*}; + my $quoted = qr{"(?:\\[^\r\n]|[^\\"])*"}; + my $local = qr{(?:$dot_atom|$quoted)}; + my $domain_lit = qr{\[(?:\\\S|[\x21-\x5a\x5e-\x7e])*\]}; + my $domain = qr{(?:$dot_atom|$domain_lit)}; + my $addr_spec = qr{$local\@$domain}; + +Just match an address against C to see if it follows +the RFC2822 specification. However, because it is impossible to be +sure that such a correctly formed address is actually the correct way +to reach a particular person or even has a mailbox associated with it, +you must be very careful about how you use this. -If you get the message back and they've followed your directions, -you can be reasonably assured that it's real. +Our best advice for verifying a person's mail address is to have them +enter their address twice, just as you normally do to change a +password. This usually weeds out typos. If both versions match, send +mail to that address with a personal message. If you get the message +back and they've followed your directions, you can be reasonably +assured that it's real. A related strategy that's less open to forgery is to give them a PIN (personal ID number). Record the address and PIN (best that it be a -random one) for later processing. In the mail you send, ask them to +random one) for later processing. In the mail you send, ask them to include the PIN in their reply. But if it bounces, or the message is -included via a ``vacation'' script, it'll be there anyway. So it's +included via a "vacation" script, it'll be there anyway. So it's best to ask them to mail back a slight alteration of the PIN, such as with the characters reversed, one added or subtracted to each digit, etc. =head2 How do I decode a MIME/BASE64 string? -The MIME-tools package (available from CPAN) handles this and a lot -more. Decoding BASE64 becomes as simple as: +The MIME-Base64 package (available from CPAN) handles this as well as +the MIME/QP encoding. Decoding BASE64 becomes as simple as: - use MIME::base64; + use MIME::Base64; $decoded = decode_base64($encoded); -A more direct approach is to use the unpack() function's "u" +The MIME-Tools package (available from CPAN) supports extraction with +decoding of BASE64 encoded attachments and content directly from email +messages. + +If the string to decode is short (less than 84 bytes long) +a more direct approach is to use the unpack() function's "u" format after minor transliterations: tr#A-Za-z0-9+/##cd; # remove non-base64 chars @@ -382,12 +481,12 @@ format after minor transliterations: =head2 How do I return the user's mail address? -On systems that support getpwuid, the $E variable and the +On systems that support getpwuid, the $< variable, and the Sys::Hostname module (which is part of the standard perl distribution), you can probably try using something like this: use Sys::Hostname; - $address = sprintf('%s@%s', (getpwuid($<))[0], hostname); + $address = sprintf('%s@%s', scalar getpwuid($<), hostname); Company policies on mail address can mean that this generates addresses that the company's mail system will not accept, so you should ask for @@ -411,7 +510,8 @@ Use the C program directly: To: Final Destination Subject: A relevant subject line - Body of the message goes here, in as many lines as you like. + Body of the message goes here after the blank line + in as many lines as you like. EOF close(SENDMAIL) or warn "sendmail didn't close nicely"; @@ -422,7 +522,12 @@ the message into the queue. This last option means your message won't be immediately delivered, so leave it out if you want immediate delivery. -Or use the CPAN module Mail::Mailer: +Alternate, less convenient approaches include calling mail (sometimes +called mailx) directly or simply opening up port 25 have having an +intimate conversation between just you and the remote SMTP daemon, +probably sendmail. + +Or you might be able use the CPAN module Mail::Mailer: use Mail::Mailer; @@ -437,51 +542,67 @@ Or use the CPAN module Mail::Mailer: The Mail::Internet module uses Net::SMTP which is less Unix-centric than Mail::Mailer, but less reliable. Avoid raw SMTP commands. There -are many reasons to use a mail transport agent like sendmail. These -include queueing, MX records, and security. +are many reasons to use a mail transport agent like sendmail. These +include queuing, MX records, and security. + +=head2 How do I use MIME to make an attachment to a mail message? + +This answer is extracted directly from the MIME::Lite documentation. +Create a multipart message (i.e., one with attachments). + + use MIME::Lite; + + ### Create a new multipart message: + $msg = MIME::Lite->new( + From =>'me@myhost.com', + To =>'you@yourhost.com', + Cc =>'some@other.com, some@more.com', + Subject =>'A message with 2 parts...', + Type =>'multipart/mixed' + ); + + ### Add parts (each "attach" has same arguments as "new"): + $msg->attach(Type =>'TEXT', + Data =>"Here's the GIF file you wanted" + ); + $msg->attach(Type =>'image/gif', + Path =>'aaa000123.gif', + Filename =>'logo.gif' + ); + + $text = $msg->as_string; + +MIME::Lite also includes a method for sending these things. + + $msg->send; + +This defaults to using L but can be customized to use +SMTP via L. =head2 How do I read mail? -Use the Mail::Folder module from CPAN -(part of the MailFolder package) or the Mail::Internet module from -CPAN (also part of the MailTools package). - - # sending mail - use Mail::Internet; - use Mail::Header; - # say which mail host to use - $ENV{SMTPHOSTS} = 'mail.frii.com'; - # create headers - $header = new Mail::Header; - $header->add('From', 'gnat@frii.com'); - $header->add('Subject', 'Testing'); - $header->add('To', 'gnat@frii.com'); - # create body - $body = 'This is a test, ignore'; - # create mail object - $mail = new Mail::Internet(undef, Header => $header, Body => \[$body]); - # send it - $mail->smtpsend or die; - -Often a module is overkill, though. Here's a mail sorter. - - #!/usr/bin/perl - # bysub1 - simple sort by subject +While you could use the Mail::Folder module from CPAN (part of the +MailFolder package) or the Mail::Internet module from CPAN (part +of the MailTools package), often a module is overkill. Here's a +mail sorter. + + #!/usr/bin/perl + my(@msgs, @sub); my $msgno = -1; $/ = ''; # paragraph reads while (<>) { - if (/^From/m) { + if (/^From /m) { /^Subject:\s*(?:Re:\s*)*(.*)/mi; $sub[++$msgno] = lc($1) || ''; } $msgs[$msgno] .= $_; - } + } for my $i (sort { $sub[$a] cmp $sub[$b] || $a <=> $b } (0 .. $#msgs)) { print $msgs[$i]; } -Or more succinctly, +Or more succinctly, #!/usr/bin/perl -n00 # bysub2 - awkish sort-by-subject @@ -490,34 +611,42 @@ Or more succinctly, $msg[$msgno] .= $_; END { print @msg[ sort { $sub[$a] cmp $sub[$b] || $a <=> $b } (0 .. $#msg) ] } -=head2 How do I find out my hostname/domainname/IP address? +=head2 How do I find out my hostname, domainname, or IP address? +X -The normal way to find your own hostname is to call the C<`hostname`> -program. While sometimes expedient, this has some problems, such as -not knowing whether you've got the canonical name or not. It's one of -those tradeoffs of convenience versus portability. +(contributed by brian d foy) -The Sys::Hostname module (part of the standard perl distribution) will -give you the hostname after which you can find out the IP address -(assuming you have working DNS) with a gethostbyname() call. +The Net::Domain module, which is part of the standard distribution starting +in perl5.7.3, can get you the fully qualified domain name (FQDN), the host +name, or the domain name. - use Socket; - use Sys::Hostname; - my $host = hostname(); - my $addr = inet_ntoa(scalar(gethostbyname($name)) || 'localhost'); + use Net::Domain qw(hostname hostfqdn hostdomain); + + my $host = hostfqdn(); + +The C module, included in the standard distribution since +perl5.6, can also get the hostname. -Probably the simplest way to learn your DNS domain name is to grok -it out of /etc/resolv.conf, at least under Unix. Of course, this -assumes several things about your resolv.conf configuration, including -that it exists. + use Sys::Hostname; -(We still need a good DNS domain name-learning method for non-Unix -systems.) + $host = hostname(); + +To get the IP address, you can use the C built-in function +to turn the name into a number. To turn that number into the dotted octet +form (a.b.c.d) that most people expect, use the C function +from the module, which also comes with perl. + + use Socket; + + my $address = inet_ntoa( + scalar gethostbyname( $host || 'localhost' ) + ); =head2 How do I fetch a news article or the active newsgroups? Use the Net::NNTP or News::NNTPClient modules, both available from CPAN. -This can make tasks like fetching the newsgroup list as simple as: +This can make tasks like fetching the newsgroup list as simple as perl -MNews::NNTPClient -e 'print News::NNTPClient->new->list("newsgroups")' @@ -529,21 +658,26 @@ available from CPAN) is more complex but can put as well as fetch. =head2 How can I do RPC in Perl? -A DCE::RPC module is being developed (but is not yet available), and -will be released as part of the DCE-Perl package (available from -CPAN). No ONC::RPC module is known. +(Contributed by brian d foy) + +Use one of the RPC modules you can find on CPAN ( +http://search.cpan.org/search?query=RPC&mode=all ). + +=head1 REVISION + +Revision: $Revision: 8539 $ + +Date: $Date: 2007-01-11 00:07:14 +0100 (Thu, 11 Jan 2007) $ + +See L for source control details and availability. =head1 AUTHOR AND COPYRIGHT -Copyright (c) 1997, 1998 Tom Christiansen and Nathan Torkington. -All rights reserved. +Copyright (c) 1997-2007 Tom Christiansen, Nathan Torkington, and +other authors as noted. All rights reserved. -When included as part of the Standard Version of Perl, or as part of -its complete documentation whether printed or otherwise, this work -may be distributed only under the terms of Perl's Artistic License. -Any distribution of this file or derivatives thereof I -of that package require that special arrangements be made with -copyright holder. +This documentation is free; you can redistribute it and/or modify it +under the same terms as Perl itself. Irrespective of its distribution, all code examples in this file are hereby placed into the public domain. You are permitted and