$ARGV[0] $Size bytes\n";
$Sum = unpack("%32C*", $OutBuf);
foreach $j (1,2) {$Sum = ($Sum & 0xffff) + int($Sum/0x10000)}
open(PIPE, "| Mail -s" .
"'$ARGV[1] part $Count/$Total size/sum $Size/$Sum' $ARGV[0]");
$j = $Count ; while (length($j) < 3 ) { $j = "0" . $j }
$j = dirname($ARGV[1])."/".$j if dirname($ARGV[1]) ne ".";
print PIPE "begin 644 ",$j,"_", basename($ARGV[1]),"\n",
pack("u",$OutBuf),"\`\nend\n";
close(PIPE) } if $Count gt 0;
$Count++; $OutBuf = $InpBuf } until $InpLen lt 1;
Perl lends itself to this application through the form of its 'read'
statement, which allows us to specify the number of bytes which it should
try to acquire into a designated string. As can be seen, we just keep
reading from standard input until an empty string is returned in
'$InpBuf'. Each time we get a non-empty string, we uuencode whatever
content is currently in '$OutBuf' and push it into a mail program. We then
store the contents of '$InpBuf' in '$OutBuf' ready for our next iteration.
Perl is able to perform a uuencode operation on a string by using its
'pack' statement as shown with a 'u' parameter; no additional modules are
required. It's not really necessary - but we also take advantage of the
'unpack' statement's characteristics to compute a checksum on each part as
it is sent.
You may observe that we actually open a pipe into the Unix/Linux 'Mail'
program to handle our outgoing mail. For greater portability, we could
install and use the Net::SMTP module.
The program can be invoked with an optional part-size parameter to adjust
its default un-encoded part-size limit of 700kb.
Programs Which Do Similar Things
Some of you may recognize that this sort of message-splitting is exactly
the sort of thing we did in "Secure Printing with PGP". For those of you
who are interested, there are updated versions of the programs presented
therein at: "CPAN Scripts Repository". Those programs use the
RFC-recommended "Base64-encode then split" methodology.
An earlier article "A Linux Client for the Brother Internet Print
Protocol" included a shell script which used a "split then send parts"
methodology; this also used Base64 encoding.
[BIO] Graham is a Unix Specialist at IBM Global Services, Australia. He
lives in Melbourne and has built and managed many flavors of proprietary
and open systems on several hardware platforms.
----------------------------------------------------------------------
Copyright (c) 2003, Graham Jenkins. Copying license
http://www.linuxgazette.com/copying.html
Published in Issue 86 of Linux Gazette, January 2003
----------------------------------------------------------------------
+------------------------------------------------------------------------+
| LINUX GAZETTE | Security with PHP Superglobals |
| ...making Linux just a little more | By David Lechnyr |
| fun! | |
+------------------------------------------------------------------------+
"Avoid strange women and temporary variables." -- Anonymous
A few years ago, my wife and I decided to go on a skiing trip up north. To
reserve skiing equipment, you had to give 24 hours advance notice using
the ski lodge's on-line website. The catch was that my wife had asked me
to make the reservations 23 hours before the deadline.
So I got to thinking, and examined the online website, which would not let
you make any reservations within the 24 hour timeframe. However, once you
selected an appropriate date, I noticed that the URL was:
https://www.somewhere.com/reservations.php?date=01-23-01
It occurred to me that, while they had locked down security on what dates
I could choose from, the final value was placed into a GET statement at
the end of the web address. I modified the web address to use
"date=01-22-01" and indeed, our skies were waiting for us first thing the
next morning (we paid for them, of course).
This innocent yet practical example is just one of the dangers we have to
be aware of when using any programming language that can be used in ways
that we did not intend, which leads us into our discussion on PHP
Superglobals.
Forms
To understand Superglobals, it is critical that you understand how data is
passed from one web page to another (e.g., forms). Specifically, you must
be aware of two methods known as GET and POST. You should also probably be
familiar with the HTML
This is standard, nothing-fancy HTML form code that asks for some
information and then submits the data to the file "process.php" . The
critical bit here is the method declaration, which tells the form how to
submit the data, for which we need to digress for a moment or two (hold
your breath):
For those that recall the early days of HTML, forms were provided by means
of the HTML tag. By inserting this tag into the HEAD of your
HTML documents, a text field appeaed where you could fill out input. As
the new HTML+ standard evolved, a
When you clicked Submit, your web browser would take the values you filled
out in the form and redirect you to this web address:
http://www.fluffygerbil.com/process.php?yourname=fred+smith&email=fred@nowhere.com&comment=I+have+no+comment
Notice how the values of the form are part of the web address itself?
That's the essence of GET.
For the curious, what is actually sent in the raw HTTP transmission to
accomplish this transaction is:
GET
/process.php?yourname=fred+smith&email=fred@nowhere.com&comment=I+have+no+comment
HTTP/1.0
Accept: image/gif, image/x-xbitmap, image/jpeg, */*
Accept-Language: en-us
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461)
Host: www.fluffygerbils.com
Connection: keep-alive
POST
With POST, the variables and their values are sent in the body of the URL
request, not the header. The advantages of this type of data transmission
is that there is no limit to the size of the data being sent since it is
contained in the body of the HTTP request, not the header. Also, if
you're using an SSL connection, the data will be encrypted too, what a
deal. :) For example, a web page that has a form statement like:
When you clicked Submit, your web browser would take the values you filled
out in the form and redirect you to this web address:
http://www.fluffygerbil.com/process.php
Notice how the values of the form are not part of the web address itself?
That's the essence of PUT.
For the curious, what is actually sent in the raw HTTP transmission to
accomplish this transaction is:
POST /process.php HTTP/1.0
Accept: image/gif, image/x-xbitmap, image/jpeg, */*
Accept-Language: en-us
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; Q312461)
Host: www.fluffygerbils.com
Content-Length: 94
Pragma: no-cache
Connection: keep-alive
yourname=fred+smith
email=fred@nowhere.com
comment=I+have+no+comment
So What?
So, why is all this background information useful? When you install PHP
4.2.2 or later, you might happen to notice that when compiling PHP, it
states:
+--------------------------------------------------------------------+
| *** NOTE *** |
| The default for register_globals is now OFF! |
| |
| If your application relies on register_globals being ON, you |
| should explicitly set it to on in your php.ini file. |
| Note that you are strongly encouraged to read |
| http://www.php.net/manual/en/security.registerglobals.php |
| about the implications of having register_globals set to on, and |
| avoid using it if possible. |
+--------------------------------------------------------------------+
Which means that PHP will be ultra-paranoid about the data that is passed
to it, and will require that you state which method the data should be
coming from. Also, you should be aware that there's more ways to send
data to your PHP pages than just via GET and POST:
Superglobals
Which brings us to Superglobals, a relatively new concept to PHP. For
example, the above diagram presents a slight problem: If you're working
with the variable $yourname, how do you know that during your script it
hasn't been redefined by one of these six other methods of variable
assignment by someone attempting to hack into your script? For example,
imagine having someone who has managed to upload a PHP script to your
webserver that performs the following (php exploit by Daniel Phoenix):
Wouldn't it be great to have a way to isolate variables based on how the
data gets assigned to it in the first place? Superglobals allow you to
specify which variables received by a specific method should be used.
Superglobals are PHP's attempt at helping you determine where a particular
value comes from. If you haven't heard of this new feature as of PHP
4.1.0, you'll want to start adapting to it. Most PHP training books don't
touch this subject, so you will need to be aware of how to transition to
this new input method. Ultimately, you should re-visit your
/usr/local/lib/php.ini file and make the following change:
register_globals = Off
This will prevent the ability for any user-submitted variable to be
injected into your PHP code and can reduce the amount of variable
poisoning a potential attacker may inflict. They will have to take the
additional time to forge submissions, and your internal variables are
effectively isolated from user submitted data. If a user then tried to
fill out a form, the server wouldn't assign any data to the global
variables $name, $email, or $comment. Instead, it would divide up the data
into the following hashed arrays:
$_POST['name']
$_POST['email']
$_POST['comment']
The main Superglobal arrays are:
1. $_GET['variable'] - Variables provided to the script via HTTP GET.
Analogous to the deprecated HTTP_GET_VARS array
2. $_POST['variable'] - Variables provided to the script via HTTP POST.
Analogous to the deprecated $HTTP_POST_VARS array
The other, less-common Superglobal arrays are:
1. $_COOKIE['variable'] - Variables provided to the script via HTTP
cookies. Analogous to the deprecated $HTTP_COOKIE_VARS array
2. $_REQUEST['variable'] - Variables provided to the script via any user
input mechanism (GET, POST, COOKIE) and which therefore cannot be
trusted.
3. $_GLOBALS['variable'] - Contains a reference to every variable which
is currently available within the global scope of the script. The keys
of this array are the names of the global variables.
4. $_SERVER['variable'] - Variables set by the web server or otherwise
directly related to the execution environment of the current script.
Analogous to the deprecated $HTTP_SERVER_VARS array
5. $_FILES['variable'] - Variables provided to the script via HTTP post
file uploads. Analogous to the deprecated $HTTP_POST_FILES array
6. $_ENV['variable'] - Variables provided to the script via the
environment. Analogous to the deprecated $HTTP_ENV_VARS array
7. $_SESSION['variable'] - Variables which are currently registered to a
script's session. Analogous to the deprecated $HTTP_SESSION_VARS array
For more details, see http://www.php.net/manual/en/reserved.variables.php.
So instead of $name being set to "John", you would either have
$_GET['name'] = "John" or possibly $_POST['name'] = "John" depending on
how the form data was submitted. The advantage is that you will know:
1. $name can never be faked; if your script sets its value, that's the
value!
2. The $_GET and $_POST arrays help you to determine if the user appended
the data as part of the URL or as part of the request body; therefore
you don't have to worry about having a form accepting POST data and
having the values change by someone sending a hacked URL with GET data
appended to the URL. This will make sense shortly, so hang on...
3. These 'superglobals' allow you to 'compartmentalize' not only your
variable's values, but how the values were provided to the server in
the first place. Someone attempting to hack into your server will have
a very difficult time bypassing this.
Final Thoughts
Programming with PHP can be a frustrating experience as of late. Security
measures prevent data from being easily assigned to variables, ISP's
typically implement PHP without consideration for their audience, and
newcomers to PHP tend to be taken aback by such terms as GET, POST,
Superglobals, and so forth. However, a little knowledge can go a long way,
and hopefully this article has helped you in your quest.
This document was prepared based on PHP 4.3.0.
Additional Resources
* On the Security of PHP, by Jordan Dimov
* A Study In Scarlet: Exploiting Common Vulnerabilities in PHP
Applications, by Shaun Clowes
This document was lovingly handcrafted on a Dell Latitude C400 laptop
running Slackware Linux 8.1.
[BIO] David is a Network Manager at the Human Resources department of the
University of Oregon. He holds a Master's Degree in Social Work along with
his MCSE+I, CNE, and CCNA certifications. He has been working with Linux
for the past six years, with an emphasis on systems security, network
troubleshooting, and PHP/MySQL integration.
----------------------------------------------------------------------
Copyright (c) 2003, David Lechnyr. Copying license
http://www.linuxgazette.com/copying.html
Published in Issue 86 of Linux Gazette, January 2003
----------------------------------------------------------------------
+------------------------------------------------------------------------+
| LINUX GAZETTE | Perl One-Liner of the Month: The Case of the |
| ...making Linux just a | Evil Spambots |
| little more fun! | By Ben Okopnik |
+------------------------------------------------------------------------+
A REPORTER'S NOTE
To forestall some sure-to-happen complaints, I'd like to underscore the
necessity of having the current version of Perl (at least 5.8.0, as of
this writing) in order to play with the scripts presented in these
articles. One-liners, to a far greater degree than proper scripts, rely on
new and unusual language features, and languages tend to "grow" new
features and drop old, outdated ones as version numbers rise. Perl,
heading for its 17th year of growth and development, is no exception.
One of a number of possible problems with one-liners is fragility,
especially in those (many of them) which are dependent on cryptocontext,
side effects, and undocumented features, which are likely - in fact, are
certain - to change without notice. One-liners are hacks which often
demonstrate some clever twist or feature, which encourages the use of all
of the above. Remember - these are fun toys which (hopefully) lead to a
better understanding of Perl; trying to use them as you would robust,
solid code would be a serious error. If you don't understand the basics of
Perl, this is not the place to start.
Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it.
-- Brian W. Kernighan
Caveat Lector (Let the reader beware).
Ben Okopnik
On board S/V "Ulysses", Saint Augustine, Florida
----------------------------------------------------------------------
Frink Ooblick had fallen asleep at the keyboard. He had been alternately
playing and trying to puzzle out the number-guessing game that Woomert had
written (the first had proven easy, but the second still eluded him); in
fact, his last unfinished game was still visible on the screen:
--------------------------------------------------------------------------
perl -wlne'BEGIN{$b=rand$=}$a=qw/Up exit Down/[($_<=>int$b)+1];print eval$a'
50
Down
25
Up
37
Up
44
Up
--------------------------------------------------------------------------
What was the secret? How did it work? [1] Frink's dreams were full of
floating bits of code which spiraled off into the distance or mutated into
monstrous shapes, threatening to consume the world. The hand shaking his
shoulder, waking him, was therefore a welcome relief. Woomert stood at his
side, looking impatient.
- "Wake up, Frink, wake up! The game's afoot, you slug-a-bed; let's go!"
- "Uh... Erm... I'm, uh, awake. What's up?"
- "In the living room. Come on, come on, there's not a moment to lose!"
Frink's first sight of their visitor brought him to a stop. Used to
dealing with the working crowd - sysadmins, techs, etc. - he had expected
the usual scruffy-and-competent look, perhaps complete with hiking boots;
what greeted his eyes was a fellow in a pinstripe suit, crisp white shirt,
a red "power" tie, and lacquered black shoes. He had been impatiently
pacing the floor, and brightened up considerably at the sight of Frink.
- "Ah, this must be the second team member in your organizational
hierarchy! Excellent; now, we can get into actualizing the power
strategies that will reorganize this, erm, unpredicted opportunity into
the profit slot on the balance sheet. All right, here's how we wind-tunnel
this: the securitization of the computing resources is predicated on
leveraging..."
Keeping a cautious eye on their visitor, Frink prison-whispered to
Woomert: "What's he saying? And what language is it in?"
- "It's Marketroid. You need to learn at least the basics of it; not that
it's spoken by the people who sign the checks - they don't have much time
for that sort of thing - but you're going to run into it in the business
world, and it's best to be prepared. Usually, though, most of these people
can still speak English; let's see if this fellow remembers how. Oh, Mr.
Wibbley!"
Their visitor had just finished what he obviously considered an
explanation of the problem, had switched off the overhead LCD projector,
put away his laser pointer, and was looking at them in an expectant
manner. Clearly, he had heard of Woomert's reputation and was relying on
the famous Hard-Nosed Computer Detective to deal with... well, whatever it
was.
- "Mr. Wibbley - that was an excellent presentation, but I wonder if you
could restate the problem in more basic terms for my assistant here. I'm
afraid he's not up on proper business terminology, and has missed the more
subtle points."
Their visitor heaved a sigh, and dropped into the nearby easy chair.
- "Oh, sure. You know, they were going to send one of the system
administrators to talk to you, but of course I insisted on doing the
presentation myself as soon as I heard about it. After all, one of them
wouldn't have even thought of using that textured salmon-and-peach
background on the slides, and that's all the rage these days! Anyway, I
did get a note from him that explains it in his own words; it's crude and
unsophisticated, not at all proper marketing technique, but I suppose you
fellows will understand it..."
The crumpled and coffee-stained napkin, most of which was covered with
calculations, reminders, and something that looked like firewall rules,
contained a short note framed with a red marker pen:
+------------------------------------------------------------------------------+
| Woomert, spambots are harvesting the e-mail addresses on our website (we've |
| tagged them with the "plus hack", [2] so we know where it's coming from); |
| the amount of spam we're getting is growing by leaps and bounds. We need to |
| have the addresses out there - it's our contact info, site problem reports, |
| etc. - but we've got to stop the 'bots somehow! I've already written the CGI |
| to handle the hot links, but we need to have the actual addresses displayed |
| on the pages, and the 'bots are getting those. Any ideas? The page is at |
| http://xxxxxxxxxxxx.xxx. I've created an account for you; just go to |
| ssh://xxxxxxxxx.xxx/xxx, password 'xxxxxxxxxx'. Thanks! |
| - Int Main |
+------------------------------------------------------------------------------+
After Woomert had ushered out their visitor (and reassured him that,
indeed, the salmon-and-peach background was delightful), he returned to
the living room where Frink awaited him.
- "What are you going to do, Woomert? Any plans?"
- "Yes; let's take a peek at their website, then get out there and look
around. It's a mistake to make decisions ahead of your facts, and we have
few facts at hand."
...
Once again, Woomert and Frink found themselves surrounded by the familiar
sights and sounds of a working web site. They could see the Web server
easily spawning off threads without significantly affecting CPU load;
clearly, the local sysadmin had installed mod_perl [3]. Here and there,
data streams whisked by, and everything moved like a smoothly-oiled
machine.
A sudden shadow made Frink look up. "What the..." Before he could go any
further, a horrifying creature, all tentacles, lenses, and evil intent [4]
leaped upon the scene, sucked up a copy of every HTML file at once, and
was gone in a blink.
- "What was that, Woomert - a spambot?"
- "Yep. These things traverse the Net, collecting e-mail addresses and
reporting them to their scummy spammer masters. Given the nature of the
Net, you can't stop them - but you can make them much less effective.
Spammers are stupid, their bots even more so, and that's what we're going
to rely on. Mind you, whatever we do is only going to be a temporary
solution; eventually, spammers (or at least their hired techie help) will
catch on to this particular method - but by then, we'll implement other
solutions."
Walking up to a convenient terminal, Woomert slipped on his favorite
typing gloves and fired off a rapid volley.
--------------------------------------------------------------------------
perl -MRFC::RFC822::Address=valid -wne'/[\w-]+@[\w.-]+/||next;print valid$&' *html
--------------------------------------------------------------------------
A line of '1's appeared on the screen; Woomert smiled and his fingers
again flew over the keyboard.
--------------------------------------------------------------------------
perl -i -wlpe's=[\w-]+@[\w.-]+=join"",map{sprintf"%s;",ord}split//,$&=e' *html
--------------------------------------------------------------------------
This time, there was no output; however, Woomert looked satisfied. He
quickly shot off an email to the local sysadmin that contained some
instructions and included a shorter version of the last one-liner -
--------------------------------------------------------------------------
perl -we'map{printf"%s;",ord}split//,pop' user@host.com
--------------------------------------------------------------------------
- "All right-o, Frink; our work here is done. Home, here we come!"
...
The old-fashioned coal-fired samovar [6] was gently perking; the zavarka
(tea concentrate), made with excellent Georgian tea, gave off a marvelous
smell. A plate of canapes, ranging from the best Russian butter and wild
blackberry jam on freshly-baked fluffy white bread to beluga caviar on a
heavy, dark rye rubbed with just a touch of garlic, was set close at hand,
and both Woomert and Frink were merrily foraging in the gourmet field thus
presented. Eventually they settled back, replete with good food, and
Frink's curiosity could be contained no longer.
- "Woomert, when I try to puzzle out your one-liners, I can only get so
far; then I run out of steam. Can you tell me about what you did?"
Lying back in his favorite armchair, Woomert smiled.
- "Instead, why don't you start by telling me what part you understood? I
like to see how far you've advanced, Frink; it's been a pleasure to me to
see you picking up some of the finer points. I'll take it from there."
- "All right, then... Let's start with the first one:
--------------------------------------------------------------------------
perl -MRFC::RFC822::Address=valid -wne'/[\w-]+@[\w.-]+/||next;print valid$&' *html
--------------------------------------------------------------------------
I recognized all the command-line switches:
-Mmodule Use the specified module
-w Enable warnings
-n Non-printing loop
-e Execute the following commands
However, I couldn't quite puzzle out the
'-MRFC::RFC822::Address=valid'syntax - what was that?"
- "Ah. As 'perldoc perlvar' tells us, in the entry for '-M', it's a bit
of syntactic sugar; '-MBar=foo' is a shortcut for 'use Bar qw/foo/', which
imports the specified function 'foo' from module 'Bar'. Go on, you're
doing well."
Frink cleared his throat.
- "In that case, I think I have it figured out... almost. Let me take a
quick look at 'perldoc perlvar' and 'perldoc RFC::RFC822::Address'... Yes,
that's what I thought - I've got it! The regex at the beginning -
/[\w-]+@[\w.-]+/
tries to match e-mail addresses - it's not perfect, but should do
reasonably well. What it says is "match any character in [a-zA-Z0-9-]
repeated one or more times, followed by '@', followed by any character in
[a-zA-Z0-9.-] repeated one or more times". If the match does not succeed -
the '||' logical-or operator handles that - go to the next line."
- "Brilliant, Frink! What happens then?"
- "If it does succeed, 'next' is skipped over, and 'print valid$&' is
invoked. The module documentation tells me that the 'valid' function tests
an e-mail address for RFC822 (e-mail specification) conformance, and
returns true or false based on validity. '$&', according to 'perldoc
perlvar', is the last successful pattern match - in other words, whatever
was matched by the regex. Since you saw all '1's and no errors - any
matches that weren't RFC822-valid would have returned something like "Use
of uninitialized value in print at -e line 1" - what you matched was all
valid. What you were doing here is checking to see that your regex only
matched actual addresses. How did I do?"
- "Excellent, my dear Frink; you're coming along well! As a side note,
it's generally best to avoid the use of $&, $`, and $' as well as 'use
English' in scripts; there's a rather large performance penalty associated
with them (see 'perldoc perlvar'). However, here we had a very small list
of matches, and so I went ahead with it. Go on, see what you can make of
the next one."
- "Um... the next one, right. Well, I've got part of it -
--------------------------------------------------------------------------
perl -i -wpe's=[\w-]+@[\w.-]+=join"",map{sprintf"%s;",ord}split//,$&=e' *html
--------------------------------------------------------------------------
-i In-place edit (modify the specified file[s])
-w Enable warnings
-p Printing loop
-e Execute the following commands
Mmmm... I got sorta lost here, Woomert. I see that regex that you'd used
before, but what's that 's=' bit?"
- "It's one of those convenient tweaks that Perl provides - although,
admittedly, the basic idea was stolen from 'sed'. It's simply an alternate
delimiter used with the 's' (substitute) operator; there are times when
using the default delimiter ("/") is highly inconvenient and leads to
"toothpick Hell" - as, for example, in matching a directory name:
s/\/path\/to\/my\/directory/my home directory/
Far better to use an alternate delimiter, one that is not contained in the
text of either the pattern or the replacement:
s#/path/to/my/directory#my home directory#
As long as it's non-alphanumeric and non-whitespace, it'll work fine.
There are some special cases, but they're all sensible ones; using a
single quote disables interpolation in both the pattern and the
replacement (see the rules in 'perldoc perlop'), and using braces or
brackets as delimiters requires rather obvious syntax:
s{a}{b}
s(a)(b)
s[a][b]
Many people like '#' as a delimiter; I prefer '=', since '#' tends to come
up in HTML and comments. Can you make sense of any of the rest?"
- "I'm afraid not. You're matching the email addresses as previously, and
replacing them with something, but I can't figure out what."
- "All right; it is rather involved. The replacement part of the
substitution is actual Perl code; we can do that thanks to the 'e'
(evaluate) modifier on the end of the 's' operator. Let's parse the
relevant code from right to left:
join"",map{sprintf"%s;",ord}split//,$&
We know that '$&' contains an email address; the next thing we do is use
the 'split' function which converts a scalar to a list, splitting it on
whatever is specified between the delimiters. In this case, however, the
delimiter is empty, a null - so the returned list has each character of
the address as a separate element in the list. We now pass this list to
the 'map' function, which will evaluate the code specified in the {block}
for each element of the supplied list and return the result - as another
list.
Within the block itself, each character is used as an argument to the
'ord' function, which returns the ASCII value of that character; this, in
turn, is used as the argument for the 'sprintf' function which returns the
following formatted string:
;
for each value so specified. After all the characters in the list have
been processed, we use the 'join' function to convert the list back to a
scalar - which the substitute operator will now use as a replacement
string for the original email address. What used to be "foo@bar.com" now
looks like
foo@bar.com
This, you must admit, looks nothing like an e-mail address - so spambots
will not be able to read it!"
Frink looked troubled.
- "Woomert, I hate to tell you... but human beings won't be able to read
it either!"
Woomert took another sip of his tea and smiled.
- "You're forgetting one thing, Frink. Humans aren't going to be reading
this; since it's part of the HTML files, it's going to be read by
browsers. As it happens, the HTML specification for showing ASCII
characters by their value is
;
which is exactly what we've produced. Try this yourself: save the text
between the following lines as "text.html" and view it in a browser.
--------------------------------------------------------------------------
Woomert Foonly
--------------------------------------------------------------------------
Do you see what I mean?"
A few moments later, Frink looked up from the keyboard.
- "Woomert, what a great solution! Your client will be able to display
the addresses without them being harvested, and the Web page will still
look the same as it did before. I can tell by comparison that the last bit
of code:
--------------------------------------------------------------------------
perl -we'map{printf"%s;",ord}split//,pop' user@host.com
--------------------------------------------------------------------------
simply enables the sysadmin to convert any new addresses before popping
them into the HTML. Wonderful!"
- "A large part of the complete solution, of course, was the CGI that the
local admin had written - that takes a bit more than a one-liner, although
not very much more, given the power of the CGI module. Remember, Frink: as
your powers grow, make certain to align yourself with the side of Good
rather than Evil. Not only is it the right thing to do; the people around
you are far more likely to have brains!"
--------------------------------------------------------------------------
[1] Oddly enough, my mysterious correspondent did not include the solution
to this, perhaps deeming it simple enough (!) for the public to figure out
- or (and I suspect this to be the more likely scenario) he has not yet
figured it out himself. Readers are welcome to write in with their
ideas... but for now, the workings of Woomert's game remain a puzzle.
[2] A number of commonly-used Mail Transfer Agents will ignore anything
that follows a plus sign in the username part of the address, e.g.
will be routed exactly the same as .
This can be a very useful mechanism for tracing and reducing spam: a
"plus-hacked" address that becomes too spam-loaded can be directed to
"/dev/null" and replaced by a newly generated one (say,
- which would also go to .)
[3] A.K.A. "Apache On Steroids". From the mod_perl documentation:
The Apache/Perl integration project brings together the full power of
the Perl programming language and the Apache HTTP server. This is
achieved by linking the Perl runtime library into the server and
providing an object oriented Perl interface to the server's C language
API.
These pieces are seamlessly glued together by the `mod_perl' server
plugin, making it is possible to write Apache modules entirely in
Perl. In addition, the persistent interpreter embedded in the server
avoids the overhead of starting an external interpreter program and
the additional Perl start-up (compile) time.
There are many major benefits to using mod_perl; if you use Apache in any
serious fashion without it, you're almost certainly throwing away some of
your time and effort.
[4] If you've seen "The Matrix", just picture the Sentinels. If you
haven't seen it, hey, you've got only yourself to blame. :)
[5] Gibberish is the written form of the Marketroid language. It was
formerly spoken by the Gibbers, who all died out as a result of their
complete inability to do anything (as opposed to talking about it.) It is
exactly as comprehensible as its spoken counterpart, although many people
confuse the two: "it's all marketroid gibberish!" is a highly redundant
statement.
[6] See the "Russian Tea HOWTO", by Daniel Nagy, for the proper way to
make and serve Russian tea. The man knows what he's talking about.
Ben is a Contributing Editor for Linux Gazette and a member of The Answer
Gang.
picture Ben was born in Moscow, Russia in 1962. He became interested in
electricity at age six--promptly demonstrating it by sticking a fork into
a socket and starting a fire--and has been falling down technological
mineshafts ever since. He has been working with computers since the Elder
Days, when they had to be built by soldering parts onto printed circuit
boards and programs had to fit into 4k of memory. He would gladly pay good
money to any psychologist who can cure him of the resulting nightmares.
Ben's subsequent experiences include creating software in nearly a dozen
languages, network and database maintenance during the approach of a
hurricane, and writing articles for publications ranging from sailing
magazines to technological journals. Having recently completed a
seven-year Atlantic/Caribbean cruise under sail, he is currently docked in
Baltimore, MD, where he works as a technical instructor for Sun
Microsystems.
Ben has been working with Linux since 1997, and credits it with his
complete loss of interest in waging nuclear warfare on parts of the
Pacific Northwest.
----------------------------------------------------------------------
Copyright (c) 2003, Ben Okopnik. Copying license
http://www.linuxgazette.com/copying.html
Published in Issue 86 of Linux Gazette, January 2003
----------------------------------------------------------------------
+------------------------------------------------------------------------+
| LINUX GAZETTE | Qubism |
| ...making Linux just a little more fun! | By Jon "Sir Flakey" Harsem |
+------------------------------------------------------------------------+
These cartoons are scaled down to minimize horizontal scrolling. To see a
panel in all its clarity, click on it.
[cartoon]
[cartoon]
All Qubism cartoons are here at the CORE web site.
[BIO] Jon is the creator of the Qubism cartoon strip and current
Editor-in-Chief of the CORE News Site. Somewhere along the early stages of
his life he picked up a pencil and started drawing on the wallpaper. Now
his cartoons appear 5 days a week on-line, go figure. He confesses to
owning a Mac but swears it is for "personal use".
----------------------------------------------------------------------
Copyright (c) 2003, Jon "Sir Flakey" Harsem. Copying license
http://www.linuxgazette.com/copying.html
Published in Issue 86 of Linux Gazette, January 2003
----------------------------------------------------------------------
+------------------------------------------------------------------------+
| LINUX GAZETTE | Programming in Ruby - Part 3 |
| ...making Linux just a little more fun! | By Hiran Ramankutty |
+------------------------------------------------------------------------+
Review
In part 1 we looked at the basic syntactic structure of Ruby. In part 2 we
discussed iterators and the fundamentals of Object-Oriented Programming.
Here in part 3 we explore object-orientedness in more detail.
Methods
A method is an action the object knows how to perform on request. Let's
see an example of how a method is invoked for an object:
print "asdfgh".length
^D
6
One can infer from this that a method named `length' of the String object
is called.
Now try this:
foo = "abc"
print foo.length,"\n"
foo = [1, 2]
print foo.length,"\n"
^D
3
2
From the result it is clear that deciding which method to call is done at
execution time, and that the choice differs depending on the content of
the variable.
I suggest that readers not bother about how the object determines its
length because the process is different for strings and arrays.
Fortunately, Ruby automatically chooses the correct process, so we don't
have to worry about it. This feature in languages supporting object
orientedness is called polymorphism.
It is not necessary for the user to know how the methods are processed,
but one has to know what methods are acceptable to the object. When an
object receives an unknown method, an error is raised. For example: try
calling the "length" method for the object "foo" with value "5".
I had mentioned about a special variable self in Ruby. It is the object
which calls methods. Such callings are used very often and so an
abbreviation is available. That is;
self.method_name(arguments...)
can be omitted then
method_name(arguments...)
causes same effect. Called function is just an abbreviation for method
calling to self.
Classes
The real world consists of objects which can be classified. For example, a
one-year-old child may think `bowwow' on seeing a dog or even a fox. In
terms of object orientedness, `bowwow' can be termed class, and an object
belonging to a class is called instance.
In Ruby, as in other object oriented languages, we first define a class to
determine the behaviour of the object, and then make an instance of the
class, a specific object. So let's define a class in Ruby.
class Dog
def bark
print "Bow wow\n"
end
end
^D
The definition of the class lies between the keywords `class' and `end'. A
`def' in class syntax defines a method of the class.
Now that we have a class named `Dog', let's make an object.
tommy = Dog.new
tommy.bark
^D
Bow wow
This makes a new instance of the class Dog and substitutes it into the
variable tommy. The method `new' of any class makes a new instance. Now
the variable tommy has properties defined in the class Dog, and so he can
`bark'.
Inheritence
Ever wondered how others classify objects? One example is how people
perceive a dog. A mathematician may see a dog as an object made up of
different numbers and figures, a physicist may see it as the result of
many natural and artificial forces at work, and my sister (a zoologist)
may interpret it as a representative of the species canine domesticus. To
her, a dog is a kind of canine, a canine is a kind of mammal, and a mammal
is always an animal.
Hence we see that the classification of objects takes the form of a
hierarchy, though not in all cases. Let's see what Ruby does with it.
class Animal
def breath
print "inhales and breaths out\n"
end
end
class Cat