Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

Perfecting some more!

by Nik
on Apr 30, 2005 at 05:28 UTC ( #452805=perlquestion: print w/replies, xml ) Need Help??
Nik has asked for the wisdom of the Perl Monks concerning the following question:

Here is how my script has been transformed thanks to your precious precious suggestions and mine's minor alternation: I dont know what to do with the long lines you said... Do i have to to use subs since this is not a big script and actually iam not repeating any functions more than once? Well, ok, i dont know if it can gets any shorten than this or if i can put tha javascript out in a seperate file but still pass the $data variable. Also maybe thre is a better wau to create the $data variable instead of constant concatenations as i have it.

#!/usr/bin/perl use strict; use warnings; use CGI::Carp qw(fatalsToBrowser); use CGI qw(:standard); use DBD::mysql; use POSIX qw(strftime); print header( -charset=>'iso-8859-7' ); print start_html( -style=>'/data/css/style.css', -title=>'Ψυχωφελή Πνευματικά Κείμενα!', -background=>'/data/images/night.gif' ); my ($sth, $row, $data); my $date = strftime( "%d %b, %H:%M", localtime ); my $host = $ENV{'REMOTE_HOST'} || $ENV{'REMOTE_ADDR'}; $host = "dell" if ( ($host eq "dell") or ($host eq "localhost") or ($h +ost =~ / ); my $dbh = ($ENV{'SERVER_NAME'} ne '') ? DBI->connect('DBI:mysql:nikos_db', 'root', '* +*******') : DBI->connect('', 'nikos_db', '* +*******') or {RaiseError=>1}; #********************************************************************* +********** my @files = <../data/text/*.txt>; my @display_files = map /([^\/]+)\.txt/, @files; print start_form(-action=>''); print p( {-align=>'center'}, span( {class=>'tip'}, "Διάλεξε ένα +από τα κείμενα για να διαβάσεις => " ), popup_menu( -name=>'select', -value +s=>\@display_files ), submit('Επιλογή')); print end_form; my %sql = ( get_row => 'SELECT * FROM visitorlog', get_counter => 'SELECT counter FROM visitorlog', get_host => 'SELECT host FROM visitorlog WHERE host=?', update => 'UPDATE visitorlog SET passage=?, counter=counter+1 + WHERE host=?', insert_host => 'INSERT INTO visitorlog (host, date, passage, count +er) VALUES (?, ?, ?, ?)' ); my $passage = param('select') || "Αρχική Σελίδα!"; if ( param('select') ) { open(FILE, "<../data/text/$passage.txt") or die $!; local $/; $data = <FILE>; close(FILE); $sth = $dbh->prepare( $sql{update} ); $sth->execute( $passage, $host ); } else { $sth = $dbh->prepare( $sql{get_host} ); $sth->execute( $host ); if ($sth->rows) { $sth = $dbh->prepare( $sql{get_row} ); $sth->execute; $row = $sth->fetchrow_hashref; $data = "Καλώς ήλθες $host! Χαίρομαι που βρίσκες την σελίδα εν +διαφέρουσα! Τελευταία φορά ήρθες εδώ ως $row->{host} στις $row->{ +date} !! Συνολικά ήρθες εδώ $row->{counter} φορές !!! Τελευταία είδες το κείμενο [ $row->{passage} ] Ποιό κείμενο θα μελετήσεις αυτήν την φορά !?"; $sth = $dbh->prepare( $sql{update} ); $sth->execute( $passage, $host ); } elsif ($host ne "dell") { $data = "Γειά σου $host! Έρχεσαι για 1η φορά εδώ !! Ελπίζω να βρείς τα κείμενα ενδιαφέροντα ;-)"; $sth = $dbh->prepare( $sql{insert_host} ); $sth->execute( $host, $date, $passage, 1 ); } else { $data = "Γειά σου Νικόλα, τι χαμπάρια?! Όλα δεξιά να σου πάνε +πάντα! ;-)"; } } for ($data) { s/\n/\\n/g; s/"/\\"/g; tr/\cM//d; } #********************************************************************* +********** print <<ENDOFHTML; <html><head><title></title> <script type='text/javascript'> var textToShow = "$data"; var tm; var pos = 0; var counter = 0; function init() { tm = setInterval("type()", 45) } function type() { if (textToShow.length != pos) { d = document.getElementById("DivText"); c = textToShow.charAt(pos++); if (c.charCodeAt(0) != 10) d.appendChild(document.createTextNode(c)); else d.appendChild(document.createElement("br")); counter++; if (counter >= 1800 && (c.charCodeAt(0) == 10 || c == ".")) { d.appendChild(document.createElement("br")); d.appendChild(document.createTextNode("Press any key...")); counter = 0; clearInterval(tm); document.body.onkeypress = function () { document.getElementById("DivText").innerHTML = ''; tm = setInterval("type()", 50); document.body.onkeypress = null; }; } } else clearInterval(tm); } </script> <body onload=init()> <center> <div id="DivText" align="Left" style=" background-image: url(../data/images/kenzo.jpg); border: Ridge Magenta 5px; width: 850px; height: 500px; color: LightSkyBlue; font-family: Times; font-size: 18px;"> </div ENDOFHTML #********************************************************************* +********** print br() x 3; print start_form(-action=>''); print table( {class=>'user_form'}, Tr( td( 'Πώς σε λένε αδελφε?' + ), td( textfield( 'name' ))), Tr( td( 'Ποιά είναι η γνώμη σου για την ευχούλα »Κύριε Ιησού Χριστέ, Ελέησον Με« ?' + ), td( textarea( -name=>'pray', -rows=>4, -columns=>25 ) +)), Tr( td( 'Περιέγραψε μας, μία προσωπική σου πνευματική εμπειρία από συζήτηση με γέροντα πρ +ος ώφελος των υπολοίπων αδελφών ( αν φυσικά έχεις + :-)' ), td( textarea( -name=>'remark', -rows=>6, -columns=>25 + ))), Tr( td( 'Ποιό είναι το email σου?' + ), td( textfield( 'email' ))), Tr( td( submit( 'Εμφάνιση Guestbook!' + )), td( submit( 'Αποστολή' ))), ); print end_form(); print br() x 2; my @tips; open(FILE, "<../data/text/tips") or die $!; @tips = <FILE>; close(FILE); @tips = grep { !/^\s*$/ } @tips; my $tip = $tips[ rand @tips ]; print table( {class=>'tip'}, Tr( td( {class=>'tip'}, $tip )) ), br; $sth = $dbh->prepare( $sql{update_counter} ) if ($host ne "dell"); $sth->execute; $sth = $dbh->prepare( $sql{get_counter} ); $sth->execute; my $pagecounter; while ($row = $sth->fetchrow_hashref) { $pagecounter += $row->{counter}; } print table( {class=>'info'}, Tr( td( {class=>'host'}, $host )), Tr( td( {class=>'date'}, $date )), Tr( td( {class=>'counter'}, $pagecounter )) ); print br(), a( {href=>''}, img{src=>'../data/ +images/games.gif'} ); print p( {-align=>'right'}, a( {href=>''}, font( + {-size=>2, -color=>'Lime'}, b( 'Last Update: 30/4/2005' ))));
How i can i shorter it, perfect it some more by dividing into subs?
What must be/not be in a sub?


$data will now contain the entire contents of /data/text/$passage.txt. That is also what i want because then a javascript follows to get the $data varibale and produce nice effects.

$data =~ s/\n/\\n/g; $data =~ s/"/\\"/g; $data =~ tr/\cM//d; print <<ENDOFHTML; <html><head><title></title> <script type='text/javascript'> var textToShow = "$data"; {snip]
also $host never gets a hostanme just ip address. I was wondering if there is a way to take out the js snippet from my but still pass the value of $data to that .js to produce the nice effects.....

Also i have to take out the backslash and " symbols or otherwise the javascript part wont work correctly since $data is enclosed to double quotes.

Is there some better way to do this as well?

Today i already updated this script 8 times!
When i amke a better version of it i'am updating the original to avoid reposting all over the beginning! ;-)

Janitored by Arunbear - added readmore tags, as per Monastery guidelines

Replies are listed 'Best First'.
Re: Perfecting some more!
by eXile (Priest) on Apr 30, 2005 at 05:48 UTC
    A few tips:

    Don't use FatalsToBrowser in production code, it's a useful tool for testing, it's a potential source for hackers to gather information of your server.

    Separate perl-code and html. You can use templating solutions for that like Template (there are more templating solutions, look around on permonks,cpan).

    For separating into subroutines, there are no strict rules, but try to split it up in places you think are logical. For instance a CGI script with several states could be split up in one subroutine per state. Experiment with it, see if you can find pieces in your code that look reusable, so if you make them into a subroutine you could use this subroutine later on in another script.

      Thanks! Any other suggestiosn on the script?
Re: Perfecting some more!
by kiat (Vicar) on Apr 30, 2005 at 08:02 UTC
    Just out of curiosity, what are your reasons for storing some of the data in a database and some in text files?

    I've most (99%) of mine stored in the database so that manipulating the data is almost always done through the database (MySQL).

    Like eXile, I really think you should move the html part out of your code. Put it in a template. I'm using HTML::Template and I'm happy ever after.

      I see!
      Well all of the user_sumbmitted variables i store them in mysql tables as well as almost any other kinf of information except the passages itself where i store them in palin text files

      I never actyally thought that i can store the whole content of a buch of files into database tables as well.
      Seems a nice idea(dotn know why though maybe of amatetr of having it all together) but how will i load the files there and most inquiry how is that going to help me?its very simple having its passage the user selects to see in its own file

      If its better the way you tell me i'll be happy to do it!
        I would move the passages to the database as well. That way, I've a consistent way of adding, editing and deleting the passages. And once in a proper database, you can add other functionalities like search capabilities. Of course, you can accomplish the search capability with text files but it's more work.
Re: Perfecting some more!
by rg0now (Chaplain) on Apr 30, 2005 at 09:54 UTC
    Ok, lately this was the second time that someone posted an entire CGI script at PerlMonks, complete with the (presumably) correct address the CGI script is (or will be) available at. (Well, actually, this is the third time. The first node was this one: Do not undertand this error message and Nik does it for the second time, too...)

    In order to understand, why this is an exceptionally bad practice, you have to be aware of the basic methodology of cracking a web page. At least 90% of the work you do when you want to abuse a web site is actually gathering of relevant information:

    • type and version of the OS and the web server software in the hope that you find a public exploit for a potentially unpatched vulnerability
    • DNS entries, phone numbers for easy social engineering
    • path names and file names of CGI scripts for code injection attacks
    • the type of the underlying database engine, valid user names known for the databases, names of tables and columns in the database tables for SQL injection attacks
    • and countless more...
    When you got all these relevant information, it is not particularly hard to devise an easy way to hack into someone's web site.

    Observe that you give all these information very nicely in your post, so you do he majority of the hard work of the attacker. And this is exactly why crackers often hang around at sysadmin forums and mailing lists: these places are invaluable sources of easy information...

    Do yourself a favour: only post stripped down versions of your CGI scripts and remove all sensitive pieces of data (as you did very cleverly with the passwords). This will also make it easier for other monks to consume your question by the way...

    Update: rephrased a bit...

      But how would one ahck my page since i use placeholder so he can insert bogun input neither he can'../../somepath/somefile') ?! By what exact way?
        Beware of the false sense of being secured, and instead, be paranoid! You can enver know, how weird ideas other might have to crack your tiny little script...

        Although using placeholders is considered to be a good practice, here SQL Injection myths under DBI? you will find an extensive discussion on this topic and a bazillion of ideas on how to crack SQL queries. Pick the one you most like!

        I think that it is more of a phylosophical question than a practical one: the point is that one should never ever post production CGI code on public forums!

Re: Perfecting some more!
by Courage (Parson) on Apr 30, 2005 at 10:00 UTC
    posting non-english text is quite impolite.

    Also consider using <readomre>tags.

      Could you explain to me why posting non-English text is impolite? IMNSHO I think it more impolite to assume the whole world is, or should, make websites in English/speak English.


      All code is usually tested, but rarely trusted.
        because I do not know if his sentence is offencive for me or not.
        its obvious.
        You never know if he pronounced f-word or not (some programmers allow for such words in their programs)

        For each language there are gazillions of web-resources by their language. Many languages is good. I respect their languages. English is far not only language on the web!

        Also, I do have respect of people knowing many languages.
        But use wisely.

        In Nik's case he just did not spent enough time to clean his message. Hence that is twice impolite.

        PS. I am Russian and able to behave similarly. But due to respect of others I only say language understandable by others.
        Those are the rules!

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://452805]
Approved by ghenry
[Eily]: I just wrote a oneliner to solve a (non perl) colleague's problem, and it worked on the first try
[Eily]: and he wasn't impressed

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (7)
As of 2017-04-26 14:58 GMT
Find Nodes?
    Voting Booth?
    I'm a fool:

    Results (482 votes). Check out past polls.