--- loncom/interface/loncommon.pm 2012/08/07 10:52:17 1.1090
+++ loncom/interface/loncommon.pm 2012/08/25 04:34:44 1.1094
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# a pile of common routines
#
-# $Id: loncommon.pm,v 1.1090 2012/08/07 10:52:17 foxr Exp $
+# $Id: loncommon.pm,v 1.1094 2012/08/25 04:34:44 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -70,6 +70,9 @@ use Apache::lonclonecourse();
use LONCAPA qw(:DEFAULT :match);
use DateTime::TimeZone;
use DateTime::Locale::Catalog;
+use Text::Aspell;
+use Authen::Captcha;
+use Captcha::reCAPTCHA;
# ---------------------------------------------- Designs
use vars qw(%defaultdesign);
@@ -887,10 +890,14 @@ sub check_uncheck_jscript {
function checkAll(field) {
if (field.length > 0) {
for (i = 0; i < field.length; i++) {
- field[i].checked = true ;
+ if (!field[i].disabled) {
+ field[i].checked = true;
+ }
}
} else {
- field.checked = true
+ if (!field.disabled) {
+ field.checked = true;
+ }
}
}
@@ -3063,41 +3070,27 @@ Note: This sub assumes that aspell is in
sub check_spelling {
my ($wordlist, $language) = @_;
+ my @misspellings;
+
+ # Generate the speller and set the langauge.
+ # if explicitly selected:
- # Format the command. If $language is null then
- # don't request a language - Note that's dangerous
- # because there's no assurance the server is running the intended default
- # language.
-
- my $langswitch = '';
+ my $speller = Text::Aspell->new;
if ($language) {
- $langswitch = "--lang=$language";
+ $speller->set_option('lang', $language);
}
- my $aspell_command = "aspell -a $language";
- my $full_command = "echo $wordlist | $aspell_command";
-
- my $ispell_result = `$full_command`;
+ # Turn the word list into an array of words by splittingon whitespace
- # The result is several lines of text.
- # the first line will start with @(#). Other wise
- # There's an error. With an error our fallback is to declare
- # all the words are correctly spelled (return empty string).
+ my @words = split(/\s+/, $wordlist);
- my @misspellings;
- my @lines = split(/\n/, $ispell_result);
- my $heading = shift(@lines); # header
- if ($heading =~ /^\@\(#\) /) {
- foreach my $word (split(/\s+/, $wordlist)) {
- my $spellok = pop(@lines);
- if (!($spellok =~ /^\*/)) {
- push(@misspellings, $word);
- }
+ foreach my $word (@words) {
+ if(! $speller->check($word)) {
+ push(@misspellings, $word);
}
- return join(' ', (@misspellings)); # empty if all words ok.
- } else {
- return "";
}
+ return join(' ', @misspellings);
+
}
# -------------------------------------------------------------- Plaintext name
@@ -13885,6 +13878,20 @@ sub init_user_environment {
\%userenv,\%domdef,\%is_adv);
}
+ $userenv{'canrequest.author'} =
+ &Apache::lonnet::usertools_access($username,$domain,'requestauthor',
+ 'reload','requestauthor',
+ \%userenv,\%domdef,\%is_adv);
+ my %reqauthor = &Apache::lonnet::get('requestauthor',['author_status','author'],
+ $domain,$username);
+ my $reqstatus = $reqauthor{'author_status'};
+ if ($reqstatus eq 'approval' || $reqstatus eq 'approved') {
+ if (ref($reqauthor{'author'}) eq 'HASH') {
+ $userenv{'requestauthorqueued'} = $reqstatus.':'.
+ $reqauthor{'author'}{'timestamp'};
+ }
+ }
+
$env{'user.environment'} = "$lonids/$cookie.id";
if (tie(my %disk_env,'GDBM_File',"$lonids/$cookie.id",
@@ -14059,6 +14066,148 @@ sub parse_supplemental_title {
return $title;
}
+sub captcha_display {
+ my ($context,$lonhost) = @_;
+ my ($output,$error);
+ my ($captcha,$pubkey,$privkey) = &get_captcha_config($context,$lonhost);
+ if ($captcha eq 'captcha') {
+ $output = &create_captcha();
+ unless ($output) {
+ $error = 'captcha';
+ }
+ } elsif ($captcha eq 'recaptcha') {
+ $output = &create_recaptcha($pubkey);
+ unless ($output) {
+ $error = 'recpatcha';
+ }
+ }
+ return ($output,$error);
+}
+
+sub captcha_response {
+ my ($context,$lonhost) = @_;
+ my ($captcha_chk,$captcha_error);
+ my ($captcha,$pubkey,$privkey) = &get_captcha_config($context,$lonhost);
+ if ($captcha eq 'captcha') {
+ ($captcha_chk,$captcha_error) = &check_captcha();
+ } elsif ($captcha eq 'recaptcha') {
+ $captcha_chk = &check_recaptcha($privkey);
+ } else {
+ $captcha_chk = 1;
+ }
+ return ($captcha_chk,$captcha_error);
+}
+
+sub get_captcha_config {
+ my ($context,$lonhost) = @_;
+ my ($captcha,$pubkey,$privkey);
+ my $hostname = &Apache::lonnet::hostname($lonhost);
+ my $serverhomeID = &Apache::lonnet::get_server_homeID($hostname);
+ my $serverhomedom = &Apache::lonnet::host_domain($serverhomeID);
+ my %domconfig = &Apache::lonnet::get_dom('configuration',[$context],$serverhomedom);
+ if (ref($domconfig{$context}) eq 'HASH') {
+ if ($domconfig{$context}{'captcha'} eq 'recaptcha') {
+ if (ref($domconfig{$context}{'recaptchakeys'}) eq 'HASH') {
+ $pubkey = $domconfig{$context}{'recaptchakeys'}{'public'};
+ $privkey = $domconfig{$context}{'recaptchakeys'}{'private'};
+ }
+ if ($privkey && $pubkey) {
+ $captcha = 'recaptcha';
+ }
+ } elsif ($domconfig{$context}{'captcha'} eq 'notused') {
+ $captcha = '';
+ } elsif ($domconfig{$context}{'captcha'} eq 'captcha') {
+ $captcha = 'captcha';
+ } else {
+ if ($context eq 'usercreation') {
+ $captcha = 'captcha';
+ }
+ }
+ }
+ return ($captcha,$pubkey,$privkey);
+}
+
+sub create_captcha {
+ my %captcha_params = &captcha_settings();
+ my ($output,$maxtries,$tries) = ('',10,0);
+ while ($tries < $maxtries) {
+ $tries ++;
+ my $captcha = Authen::Captcha->new (
+ output_folder => $captcha_params{'output_dir'},
+ data_folder => $captcha_params{'db_dir'},
+ );
+ my $md5sum = $captcha->generate_code($captcha_params{'numchars'});
+
+ if (-e $Apache::lonnet::perlvar{'lonCaptchaDir'}.'/'.$md5sum.'.png') {
+ $output = ''."\n".
+ &mt('Type in the letters/numbers shown below').' '.
+ '
'.
+ '
';
+ last;
+ }
+ }
+ return $output;
+}
+
+sub captcha_settings {
+ my %captcha_params = (
+ output_dir => $Apache::lonnet::perlvar{'lonCaptchaDir'},
+ www_output_dir => "/captchaspool",
+ db_dir => $Apache::lonnet::perlvar{'lonCaptchaDb'},
+ numchars => '5',
+ );
+ return %captcha_params;
+}
+
+sub check_captcha {
+ my ($captcha_chk,$captcha_error);
+ my $code = $env{'form.code'};
+ my $md5sum = $env{'form.crypt'};
+ my %captcha_params = &captcha_settings();
+ my $captcha = Authen::Captcha->new(
+ output_folder => $captcha_params{'output_dir'},
+ data_folder => $captcha_params{'db_dir'},
+ );
+ my $captcha_chk = $captcha->check_code($code,$md5sum);
+ my %captcha_hash = (
+ 0 => 'Code not checked (file error)',
+ -1 => 'Failed: code expired',
+ -2 => 'Failed: invalid code (not in database)',
+ -3 => 'Failed: invalid code (code does not match crypt)',
+ );
+ if ($captcha_chk != 1) {
+ $captcha_error = $captcha_hash{$captcha_chk}
+ }
+ return ($captcha_chk,$captcha_error);
+}
+
+sub create_recaptcha {
+ my ($pubkey) = @_;
+ my $captcha = Captcha::reCAPTCHA->new;
+ return $captcha->get_options_setter({theme => 'white'})."\n".
+ $captcha->get_html($pubkey).
+ &mt('If either word is hard to read, [_1] will replace them.',
+ '').
+ '
';
+}
+
+sub check_recaptcha {
+ my ($privkey) = @_;
+ my $captcha_chk;
+ my $captcha = Captcha::reCAPTCHA->new;
+ my $captcha_result =
+ $captcha->check_answer(
+ $privkey,
+ $ENV{'REMOTE_ADDR'},
+ $env{'form.recaptcha_challenge_field'},
+ $env{'form.recaptcha_response_field'},
+ );
+ if ($captcha_result->{is_valid}) {
+ $captcha_chk = 1;
+ }
+ return $captcha_chk;
+}
+
=pod
=back