Permalink
Browse files

Merge remote branch 'remotes/petdance/master'

Conflicts:
	crank
  • Loading branch information...
shlomif committed Feb 13, 2010
2 parents 1054f29 + 8b6be7d commit 87b70b834bae203f8a7dcb406cccf53233892f73
View
@@ -0,0 +1,3 @@
+*~
+build/
+.DS_Store
View
25 INSTALL
@@ -0,0 +1,25 @@
+These are short installation instructions. They contain what needs to be done
+in order to install and play around with the Perl101.org codebase.
+
+- Install a webserver (apache, lighttpd, etc.).
+- Create the "build" folder for the "crank" script.
+- Make sure that the "href" path defined in "section.tt"'s javascript matches
+ where your CGI folder will be. It assumes it well be in "/cgi-bin".
+- Make sure that the path for the captcha pictures hardcoded in
+ "tt/show_captcha.tt" is good for you.
+- If you need to adjust the path in "show_captcha.tt", recompile the templates
+ using the following command:
+ $ jemplate --compile tt/show_captcha.tt tt/show_result.tt > static/js/jmpls.js
+ (you must have Jemplate installed)
+- Run the crank script.
+- Copy the built HTML files in your "build" folder into the document root of
+ your Perl101.
+- Copy the "static" folder to the same document root.
+- Copy over the formmail.pl and auth.pl into the appropriate CGI folder
+ (usually this would be "cgi-bin")
+- Make sure the paths for $data_folder in both files reflects where you want
+ to keep the captchas. I would recommend writing a full path.
+- Change the $recipient to your email address in "formmail.pl".
+ (you can comment off the entire Email::Stuff part to avoid emails entirely)
+
+Written by Sawyer X (2009)
View
@@ -2,24 +2,23 @@
crank \
clean
+BUILD=build
+SOURCE=s
+
default: crank
-crank:
- rm -fr 101/*.html
- mkdir 101/ || true > /dev/null 2>&1
- perl crank 101.pod
- rsync -azu --delete \
- --exclude=.svn --exclude='*~' \
- static/ 101/static/
- rsync -azu --delete \
- --exclude=.svn --exclude='*~' \
- s/ 101/s/
- cp s/*.ico 101/
+crank: clean
+ mkdir -p $(BUILD)/ || true > /dev/null 2>&1
+ perl crank --podpath=$(SOURCE) --buildpath=$(BUILD)
+ cp -R static/* $(BUILD)/
clean:
- rm -fr 101/
+ rm -fr $(BUILD)
+
+test: crank
+ prove t/html.t
# This is only useful for Andy
rsync:
- rsync -azu -e ssh --delete \
- 101/ petdance@midhae.pair.com:~/p/
+ rsync -azu -e ssh --delete --verbose \
+ $(BUILD)/ andy@huggy.petdance.com:/srv/p101
View
59 README
@@ -0,0 +1,59 @@
+These should be instructions for how the crank operation works,
+what the directory structure is and how to generate perl101.org.
+
+If anything is unclear, feel free to email me at xsawyerx@cpan.org or send
+a patch for the documentation.
+
+Perl101.org code has several components:
+* The (source) POD files under the "s" folder:
+ The POD files are the core content of perl101.org. It's written in
+ POD form. You can read the documentation of how to write POD on perldoc,
+ using either the command "perldoc perlpod" or googling for "perlpod".
+ These POD files are renderes to HTML by the generator script documented
+ below.
+
+* The static JS, images and design under the "static" folder:
+ Some things are static, such as images, the CSS layout, javascript
+ functions and the sorts. You can find those in the "static" folder.
+ There is basic CSS for handheld, print and web.
+ Currently the only image is the Perl101 logo.
+ The Javascript files are the Jemplate engine (Jemplate can be found on
+ CPAN) and a compiled Template Toolkit template file to Javascript.
+
+* The Template::Toolkit templates under the "tt" folder:
+ The generation engine uses the HTMLified POD content in templates in order
+ to render the complete website. These are the templates in the "tt" folder.
+ There is one single template called "show.tt" which is not directly used.
+ It is compiled to javascript using "jemplate" command line tool and then
+ put in the JS folder in "static".
+
+ Each section in Perl101.org is rendered independently using the
+ "section.tt" template. If you want to control each section, that's the
+ template you want to check out.
+
+ It's simple HTML with Template::Toolkit tags. Template::Toolkit can be
+ found on CPAN.
+
+* All the generated files under the "build" folder:
+ Once the generation script generated the files, it saves them in the
+ "build" folder. The folder doesn't exist by default (Perl101.org is on
+ Github.com and Git cannot monitor empty folders so you'll need to create
+ this folder yourself. The generation script will alert you if it is
+ missing.
+
+ This folder can be seen as the "htdocs" or "httpdocs" people are used
+ to.
+
+* The CGI scripts used for mailing and image creation, in the main folder:
+ Right now there are only two scripts:
+ - "auth.pl": this script is not production-ready yet. It's creates
+ captchas for the feedback form. It will try to create them in the
+ default 'captcha' folder. You'll probably have to create it.
+ - "formmail.pl": this script sends the form submitted (via AJAX)
+ and returns an answer or error.
+
+* The generator script in the main folder:
+ The generator script goes over all the POD files in "s", renders them using
+ the templates in folder "tt" and then puts them as static files in the
+ "build" folder. You can specify a different "build" folder or it will
+ by default look for a folder named "build".
View
91 auth.pl
@@ -0,0 +1,91 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use File::stat;
+use File::Spec;
+use File::Slurp;
+use Digest::MD5 'md5_hex';
+use CGI::Simple;
+use Authen::Captcha;
+use GD::SecurityImage;
+
+sub create_formula {
+ my @numbers = ( 0 .. 20 );
+ my %operators = (
+ '+' => sub { $_[0] + $_[1] },
+ '-' => sub { $_[0] - $_[1] },
+ '*' => sub { $_[0] * $_[1] },
+ '/' => sub { $_[0] * $_[1] },
+ );
+ my ( $num1, $op, $num2, $accepted );
+
+ while ( ! $accepted ) {
+ $num1 = $numbers[ rand scalar @numbers ];
+ $num2 = $numbers[ rand scalar @numbers ];
+ $op = ( keys %operators )[ rand scalar keys %operators ];
+
+ # avoiding edge cases in division
+ if ( $op eq '/' ) {
+ if ( $num2 == 0 ) {
+ # avoiding division by zero
+ next;
+ } elsif ( $num1 % $num2 != 0 ) {
+ # check if easily divisable
+ next;
+ }
+ }
+
+ $accepted++;
+ }
+
+ return [ "$num1 $op $num2", $operators{$op}->( $num1, $num2 ) ];
+}
+
+sub create_image {
+ my $text = shift;
+
+ # Create a normal image
+ my $image = GD::SecurityImage->new(
+ width => 100,
+ height => 50,
+ lines => 3,
+ #gd_font => 'giant',
+ rndmax => 3,
+ );
+
+ $image->random($text);
+ $image->create(normal => 'rect');
+
+ return $image;
+}
+
+my $cgi = CGI::Simple->new();
+my $data_folder = 'captchas';
+my ( $formula, $result ) = @{ create_formula() };
+my $md5sum = md5_hex($result);
+my $image = create_image($formula);
+my $really_delete = 1; # set to 0 or '' for testing purposes
+my $captcha_timeout = 10; # allow them to exit for 1 minute
+
+-d $data_folder || die "Cannot find data folder ($data_folder)";
+
+my ( $image_data, $mime_type, $random_number ) = $image->out;
+my $image_filename = File::Spec->catfile( $data_folder, "$md5sum.png" );
+
+# write the new file
+write_file( $image_filename, { binmode => ':raw' }, $image_data );
+
+# delete older files
+my $captcha_regex = qr/^\w+\.png$/;
+
+foreach my $file ( read_dir($data_folder) ) {
+ $file =~ $captcha_regex || next;
+ my $filename = File::Spec->catfile( $data_folder, $file );
+
+ if ( stat($filename)->ctime() < ( time() - $captcha_timeout ) ) {
+ $really_delete && unlink $filename;
+ }
+}
+
View
54 crank
@@ -3,20 +3,42 @@
use strict;
use warnings;
-BEGIN {
- eval 'use Carp::Always';
-}
+use Carp::Always;
+use Getopt::Long;
+use File::Slurp;
+use Pod::Simple 3.13;
use Template ();
use Template::Constants qw( :debug :chomp );
+my $podpath = 's';
+my $buildpath = 'build';
+
+GetOptions(
+ 'podpath:s' => \$podpath,
+ 'buildpath:s' => \$buildpath,
+) or exit;
+
+if ( ! -d $buildpath || ! -w $buildpath ) {
+ die "Buildpath ($buildpath) doesn't exist or is not writable";
+}
+
my %defaults = (
+<<<<<<< HEAD
INCLUDE_PATH => [ qw( tt ) ],
OUTPUT_PATH => $ENV{'PERL101_OUT_PATH'} || '/srv/p101/',
DEBUG => DEBUG_UNDEF,
TRIM => CHOMP_ALL,
PRE_CHOMP => 1,
POST_CHOMP => 1,
+=======
+ INCLUDE_PATH => [ qw( tt ) ],
+ OUTPUT_PATH => $buildpath,
+ DEBUG => DEBUG_UNDEF,
+ TRIM => CHOMP_ALL,
+ PRE_CHOMP => 1,
+ POST_CHOMP => 1,
+>>>>>>> remotes/petdance/master
);
my $tt = Template->new( \%defaults );
@@ -25,26 +47,26 @@ my $vars = {};
my @podfiles;
my @sidelinks;
-for ( get_sections( 's/' ) ) {
+for ( get_sections( $podpath ) ) {
my ($sectionfile, $sectiontext) = @{$_};
- my $podfile = "s/$sectionfile.pod";
+ my $podfile = "$podpath/$sectionfile.pod";
my $htmlfile = "$sectionfile.html";
push( @sidelinks, {
filename => $htmlfile,
- text => $sectiontext,
+ text => $sectiontext,
} );
push( @podfiles, {
- section => $sectiontext,
- podfile => $podfile,
+ section => $sectiontext,
+ podfile => $podfile,
htmlfile => $htmlfile,
} );
}
for my $vars ( @podfiles ) {
$vars->{content} = pod2html( $vars->{podfile} );
$vars->{sidelinks} = \@sidelinks;
- $tt->process( 'section.tt', $vars, $vars->{htmlfile} ) || die $tt->error;
+ $tt->process( 'page.ttml', $vars, $vars->{htmlfile} ) || die $tt->error;
}
sub get_sections {
@@ -87,13 +109,16 @@ sub pod2html {
$parser->html_header_after_title( '' );
$parser->html_footer( '' );
+ # Manually adjust the stuff we passed thru earlier
+ my $podtext = read_file( $podfile );
+
+ $podtext =~ s{P<(.+?)>}{L<$1|http://perldoc.perl.org/$1.html>}g;
+ $podtext =~ s{M<(.+?)>}{L<$1|http://search.cpan.org/perldoc?$1>}g;
+
$parser->complain_stderr( 1 );
$parser->output_string( \$html );
- $parser->parse_file( $podfile );
+ $parser->parse_string_document( $podtext );
- # Manually adjust the stuff we passed thru earlier
- $html =~ s{P<(.+?)>}{<a href="http://perldoc.perl.org/$1.html">$1</a>}g;
- $html =~ s{M<(.+?)>}{<a href="http://search.cpan.org/perldoc?$1">$1</a>}g;
return $html;
}
@@ -120,6 +145,9 @@ sub new {
$tagmap->{"/$code"} = ">";
}
+ $tagmap->{'VerbatimFormatted'} =
+ qq{\n<pre class="prettyprint lang-perl">\n};
+
return $self;
}
View
@@ -0,0 +1,48 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use CGI; # or CGI::Simple ?
+use JSON::XS;
+use Email::Stuff;
+
+sub error {
+ my $error_msg = shift;
+
+ # we don't really need those since we're updating the page with Jemplate
+ #my $return_link_url = $cgi->param('return_link_url') || q{};
+ #my $return_link_title = $cgi->param('return_link_title') || q{};
+
+ print encode_json { error => $error_msg };
+
+ exit 0;
+}
+
+my $cgi = CGI->new();
+
+print $cgi->header( -charset => 'UTF-8' );
+
+my $subject = $cgi->param('subject') || q{};
+my $name = $cgi->param('realname') || q{};
+my $email = $cgi->param('email') || q{};
+my $text = $cgi->param('text') || q{};
+my $recipient = q{andy@petdance.com}; # this shouldn't be in the form
+my $from = qq{$name <$email>};
+
+if ( !$name || !$text ) {
+ # a name and text are essential
+ error('Missing name or text');
+}
+
+# this should work but it didn't for me
+# maybe it was my sendmail definitions
+# but i didn't have the time to debug it
+Email::Stuff->from($from)
+ ->to($recipient)
+ ->text_body($text)
+ ->subject($subject)
+ ->send;
+
+print encode_json { success => 'imminent' };
+
Oops, something went wrong.

0 comments on commit 87b70b8

Please sign in to comment.